Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>@Jordan firstly as commenters noted, when using deferred lib, your first example definitely produces result you expect:</p> <pre><code>promise1 rejected promise2 rejected promise3 rejected </code></pre> <p>Secondly, even if it would produce output you suggest, it wouldn't affect execution flow of your second snippet, which is a bit different, more like:</p> <pre><code>promise.then(function(first_value) { console.log('promise1 resolved'); var promise = db.put(first_value); promise.then(function (second_value) { console.log('promise2 resolved'); var promise = db.put(second_value); promise.then( function (wins) { console.log('promise3 resolved'); }, function (err) { console.log('promise3 rejected'); return err; }); }, function (err) { console.log('promise2 rejected'); return err;}); }, function (err) { console.log('promise1 rejected'); return err}); </code></pre> <p>and that, in case of first promise being rejected will just output:</p> <pre><code>promise1 rejected </code></pre> <p>However (<strong>getting to the most interesting part</strong>) even though deferred library definitely returns <code>3 x rejected</code>, most of other promise libraries will return <code>1 x rejected, 2 x resolved</code> (that leads to assumption you got those results by using some other promise library instead).</p> <p>What's additionally confusing, those other libraries are more correct with their behavior. Let me explain.</p> <p>In a sync world counterpart of "promise rejection" is <code>throw</code>. So semantically, async <code>deferred.reject(new Error())</code> in sync equals to <code>throw new Error()</code>. In your example you're not throwing errors in your sync callbacks, you just returning them, therefore you switch to success flow, with an error being a success value. To make sure rejection is passed further, you need to re-throw your errors:</p> <pre><code>function (err) { console.log('promise1 rejected'); throw err; }); </code></pre> <p>So now question is, why do deferred library took returned error as rejection?</p> <p>Reason for that, is that rejection in deferred works a bit different. In deferred lib the rule is: <strong>promise is rejected when it's resolved with an instance of error</strong>, so even if you do <code>deferred.resolve(new Error())</code> it will act as <code>deferred.reject(new Error())</code>, and if you try to do <code>deferred.reject(notAnError)</code> it will throw an exception saying, that promise can be rejected only with instance of error. That makes clear why error returned from <code>then</code> callback rejects the promise.</p> <p>There is some valid reasoning behind deferred logic, but still it's not on par with how <code>throw</code> works in JavaScript, and due to that this behavior is scheduled for change with version v0.7 of deferred.</p> <p>Short summary:</p> <p>To avoid confusion and unexpected results just follow the good practice rules:</p> <ol> <li>Always reject your promises with an error instances (follow rules of sync world, where throwing value that's not an error is considered a bad practice).</li> <li>Reject from sync callbacks by <strong>throwing</strong> errors (returning them doesn't guarantee rejection).</li> </ol> <p>Obeying to above, you'll get both consistent and expected results in both deferred and other popular promise libraries.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload