Chained promises not passing on rejection
To me, this result doesn't make sense. By attaching to this promise chain, each then is implying the intent that it will be dependant upon the successful resolution of d1 and a result being passed down the chain
No. What you are describing is not a chain, but just attaching all the callbacks to d1
. Yet, if you want to chain something with then
, the result for promise2
is dependent on the resolution of promise1
and how the then
callbacks handled it.
The docs state:
Returns a new promise for the result of the callback(s).
The .then
method is usually looked upon in terms of the Promises/A specification (or the even stricter Promsises/A+ one). That means the callbacks shell return promises which will be assimilated to become the resolution of promise2
, and if there is no success/error handler the respective result will in case be passed directly to promise2
- so you can simply omit the handler to propagate the error.
Yet, if the error is handled, the resulting promise2
is seen as fixed and will be fulfilled with that value. If you don't want that, you would have to re-throw
the error, just like in a try-catch clause. Alternatively you can return a (to-be-)rejected promise from the handler. Not sure what Dojo way to reject is, but:
var d1 = d();
var promise1 = d1.promise.then(
function(wins) { console.log('promise1 resolved'); return wins;},
function(err) { console.log('promise1 rejected'); throw err;});
var promise2 = promise1.then(
function(wins) { console.log('promise2 resolved'); return wins;},
function(err) { console.log('promise2 rejected'); throw err;});
var promise3 = promise2.then(
function(wins) { console.log('promise3 resolved'); return wins;},
function(err) { console.log('promise3 rejected'); throw err;});
d1.reject(new Error());
How is Bob able to get a blue widget from Ginger when didn't get any herself?
He should not be able. If there are no error handlers, he will just perceive the message (((from the distributor) from John) from Ginger) that there are no widgets left. Yet, if Ginger sets up an error handler for that case, she still might fulfill her promise to give Bob a widget by giving him a green one from her own shack if there are no blue ones left at John or his distributor.
To translate your error callbacks into the metapher, return err
from the handler would just be like saying "if there are no widgets left, just give him the note that there are no ones left - it's as good as the desired widget".
In the database situation, if the db.query failed, it would call the err function of the first then
…which would mean that the error is handled there. If you don't do that, just omit the error callback. Btw, your success callbacks don't return
the promises they are creating, so they seem to be quite useless. Correct would be:
var promise = db.query({parent_id: value});
promise.then(function(query_result) {
var first_value = {
parent_id: query_result[0].parent_id
}
var promise = db.put(first_value);
return promise.then(function(first_value_result) {
var second_value = {
reference_to_first_value_id: first_value_result.id
}
var promise = db.put(second_value);
return promise.then(function(second_value_result) {
return values_successfully_entered();
});
});
});
or, since you don't need the closures to access result values from previous callbacks, even:
db.query({parent_id: value}).then(function(query_result) {
return db.put({
parent_id: query_result[0].parent_id
});
}).then(function(first_value_result) {
return db.put({
reference_to_first_value_id: first_value_result.id
});
}.then(values_successfully_entered);
Angular 2 chained Promise and passing on reject
See https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch
You need to throw an exception in the catch handler for example to reject the second chain.
// First chain, no problem
promise.then(data => {
console.log('Success callback', data); // This will not be called
}).catch(err => {
console.log('Error callback', err); // This will NOT be called
throw "zonk";
})
Why is onRejected not called following Promise.all() where Promise.reject() included in array passed to Promise.all()?
What you've really done here is something like this:
https://jsfiddle.net/9gprLc7q/5/
var notRejectedPromise =
Promise.reject("b")
.then((resolved) => resolved, (err) => err)
var promises = [Promise.resolve("a"), notRejectedPromise];
Promise.all(promises)
.then(function(complete) {
console.log("all promises after .map()", complete)
}, function(err) {
console.log("err", err)
})
But deciding to handle the err portion by returning whatever err
was, you returned a string. This is not a reason for rejection.
To actually cause the Promise.all()
to reject you need an error to occur in either the resolved
or rejected
portion of .then
Given this, if you return a rejected promise, it will reject:
https://jsfiddle.net/9gprLc7q/3/
console.log(err)
to
return Promise.reject(err)
Alternatively you can throw an error: https://jsfiddle.net/9gprLc7q/2/
console.log(err)
to
throw new Error(err)
Why do JavaScript promises chain rejections into resolved promises?
This is the same behavior as AngularJS's $q
provider.
The mutation occurs because in your rejection handler, you are returning a value and not a rejected promise. If you were to instead, pass a rejected promise, it would behave how you were expecting:
let p = Promise.reject().then(function () {
return 'one';
}, function() {
return Promise.reject('two');
});
p.then(function (value) {
// I do not expect this to be executed, since it was not resolved.
console.log(value);
}, function() {
console.log("Rejected, baby!");
});
Chaining promises but continue with the next promise when one fails (and log the rejection)
You can handle the rejection within the reduce
callback;
funcs.reduce((prev, cur) => prev.then(cur).catch(log), starting_promise)
Or you could pre-process the array of functions:
funcs.map(f => v => f(v).catch(log))
.reduce((prev, cur) => prev.then(cur), starting_promise)
In either case, the point is that the catch
puts the promise back on the success track, as it were (unless you throw inside the catch handler).
Note that whatever the catch
handler returns becomes the input value to the next function in the promise chain. If you want the rejection reason to become the input, then return it from the catch
handler:
function log(reason) {
console.log("rejected with reason", reason, "continuing...");
return reason;
}
From a comment:
How do I use the cur reference in the catch -> log function?
Instead of just passing log
to the catch
, pass a function which calls log
with both the reason and the function:
funcs.reduce(
(prev, cur) => prev.then(cur).catch(reason => log(reason, cur)),
starting_promise)
function log(reason, func) {
console.log("rejected with reason", reason, "in function", func, "continuing...");
return reason;
}
Why catch at the end of promise chain is not catching all the errors?
Looks like the issue is that isUsed
is being executed immediately rather than after inBlacklist
resolves, so your .then()
is being given a Promise object rather than a callback function. It's just like if you wrote a(b(c));
, b
is executed first and then the return value is passed to a
.
Instead, you want to pass to .then
a callback function that executes the next function, so try using arrow functions inside the then
s, like so:
inBlacklist(address)
.then(() => isUsed(payments))
.then(() => isProcessed(ref_num))
.then(() => validateType(type))
.catch((err) => {
console.log(err);
return res.status(400).send({ message: err.message });
});
Can a chain be stopped without sending an error message to the console?
Both .then(success, error)
callbacks return promises.
That is:
Promise.reject()
.then(function () {
// won't be called, as above promise is rejected
}, function () {
// will be called, and returns a resolved promise by default;
// if you want the next error callback to be called,
// you need to return a rejected promise or to throw an error
})
.then(function () {
// 1: called if above .then returns a resolved promise
}, function () {
// 2: called if above .then returns a rejected promise or throws an error
})
Where is the executor code for a chained promise in javascript?
Essentially each promise that's created from each then()
gets resolved/rejected automatically based on the return status of the callback function. If you reject the promise by either returning a rejected promise (return Promise.reject(err)
), throwing an error, or if an error occurs, it will call the 2nd callback (error handler) of the next .then()
. So, if you want to chain promises and keep calling the error handler, you need to keep rejecting the promise. Returning a valid value will resolve the first promise, which is why your "success" callback gets called in the 2nd .then()
You can also manually return a Promise()
from .then()
and have it immediately resolve/reject based on the logic.. promises don't have to have async logic inside of them
function testPromise(isSuccess) {
new Promise((resolve, reject) => {
setTimeout(() => {
if (isSuccess) { resolve("Success!"); }
else { reject(new Error("NOT SUCCESS!")); }
}, 1000)
}).then((res) => {
console.log("Inside 1st .then success:", res);
return res;
}, (err) => {
console.log("Inside 1st .then error:", err.message);
// return Promise.reject(err); // this also works to reach next error handler
// throw err; // this also works to reach next error handler
return new Promise((resolve, reject) => reject(err));
}).then((res) => {
console.log("Inside 2nd .then success:", res);
}, (err) => {
console.log("Inside 2nd .then error:", err.message);
})
}
testPromise(true);
testPromise(false);
Related Topics
Console.Log() Shows the Changed Value of a Variable Before the Value Actually Changes
Changing the Image Source Using Jquery
Response to Preflight Request Doesn't Pass Access Control Check
How to Find Object in Array by Property in JavaScript
Use :Hover to Modify the CSS of Another Class
How to Set Prefixed CSS3 Transitions Using JavaScript
Setting Rounded Corners for Svg:Image
Making Facebook Login Work with an Android Webview
Get Contenteditable Caret Position
Difference Between Innertext, Innerhtml and Value
Chrome: Timeouts/Interval Suspended in Background Tabs
How to Set the Caret (Cursor) Position in a Contenteditable Element (Div)
Best Way to Detect When a User Leaves a Web Page
Why Is Null an Object and What's the Difference Between Null and Undefined
Load Less.Js Rules Dynamically
Can Jquery Change CSS Style Definition? (Not Individual CSS of Each Element)