How is the error caught, when I return a promise from function A to function B, return the data from A's then, and both calls catch on the Promise? I know, when promise is resolved, A's then always gets executed first, followed by B's then with the data returned from A's then. But I can't wrap my head around how errors are caught, when this kind of returning of Promises forms a long chain. Here is the simplified sample of the scenario. I'm using Redux-thunk action creators to manage the state.
function postActionCreator(data) {
return (dispatch) => {
dispatch(type: POST_LOADING)
return Source.post()
.then(response => {
dispatch(type: POST_SUCCESS, payload: response)
return response
})
.catch(error => {
// Is this catch called if handlePost throws error in then?
dispatch(type: POST_ERROR, payload: error)
throw new Error(error)
})
}
}
// Container component's post function calling the Redux action creator
function handlePost(data) {
this.props.postActionCreator(data)
.then(response => {
// Do something with response
})
.catch(error => {
// Or is the error caught with this catch?
})
}
// Or are the both catchs called, in which order and why?
How is the error handled in these three different scenarios:
When using promises, a function should do one of three things:
For this question, we're not too concerned with the first two cases, but you can read about the promises resolution procedure here for more information. So let's take a look at that error case.
In JavaScript, errors - like most things - are just objects. Creating an error and choosing how to propagate that error are two different things. The two broad categories of propagating errors are synchronously and asynchronously. To propagate an error synchronously, you must throw
it, for async, you just pass your error object through some predefined convention (such as a callback or promise).
To answer the question fully, we need to understand how to handle these two different error types. For synchronous errors (that have been thrown), the only way to handle them (aside from a catch all event handler like window.onerror
) is to wrap them in a try/catch
statement. For async errors, we just follow the conventions of how to pass this data back up the call stack.
So to answer your question with that knowledge:
Source.post throws an error
If I assume by "throws an error" you mean that "an error occurred", we can't know how this will behave without knowing the source code of Source.post
. If an error was actually thrown, let's say there's some unexpected ReferenceError
, then it won't actually be handled at all:
function post() {
foo.bar; // will throw
}
function run() {
post()
.then(log)
.catch(log);
}
Would result in:
ReferenceError: foo is not defined
at post (sync.js:6:3)
at run (sync.js:10:3)
at Object.<anonymous> (sync.js:15:1)
Now if the post
function actually handled an error asynchronously, in this case by confirming to the promise conventions for passing errors, we'd see that it would get caught:
function post() {
return new Promise((resolve, reject) => {
reject('foo');
});
}
function run() {
post()
.then(() => {})
.catch((err) => {
console.error('Caught error:', err);
});
}
Results in
Caught error: foo
One more interesting part to this is that your code, in the catch
statement actually throws a new Error
object. In this case, we have one final thing to understand. We know that throwing an error synchronously means that it must be caught, but throwing an error from within a then
function results in a rejected exception, not an error, so what's going on? Well, the promise implementation is internally wrapping the function you pass to then
in a try/catch
block, then handling this error by rejecting the promise. We can demonstrate this like so:
function post() {
return new Promise((resolve, reject) => {
resolve('foo');
});
}
function run() {
post()
.then((result) => {
throw result;
})
.catch((err) => {
console.error('Caught error:', err);
});
}
In this case, the error is also caught.
postActionCreator's then throws an error
This now becomes simple. An error in a then
is caught and propagated. It reaches the catch
within postActionCreator
then is rethrown to the outside catch
.
handlePost's then throws an error
The simplest case. It'll be caught internally and you'll get the error in the catch
statement immediately after the then
.
And finally, you may be thinking, "how can I handle those synchronous errors in Source.post
? What if that's not my function?". Good question! You can use a utility like promise.try from Bluebird to wrap this function for you.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.