Javascript 复杂承诺-返回链中的承诺-捕获()顺序
当我从函数a向函数B返回一个承诺,然后从函数a返回数据,并且两个调用都遵守承诺时,错误是如何捕获的?我知道,当承诺得到解决时,A总是首先执行,然后是B,然后是A返回的数据。但是,当这种承诺的回报形成一条长长的链条时,我无法理解错误是如何被抓住的。下面是该场景的简化示例。我正在使用Redux thunk动作创建者来管理状态Javascript 复杂承诺-返回链中的承诺-捕获()顺序,javascript,exception,asynchronous,promise,redux,Javascript,Exception,Asynchronous,Promise,Redux,当我从函数a向函数B返回一个承诺,然后从函数a返回数据,并且两个调用都遵守承诺时,错误是如何捕获的?我知道,当承诺得到解决时,A总是首先执行,然后是B,然后是A返回的数据。但是,当这种承诺的回报形成一条长长的链条时,我无法理解错误是如何被抓住的。下面是该场景的简化示例。我正在使用Redux thunk动作创建者来管理状态 function postActionCreator(data) { return (dispatch) => { dispatch(type: POST_L
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?
在这三种不同的情况下如何处理错误:
- Source.post抛出和错误
- postActionCreator然后抛出一个错误
- 然后handlePost会抛出一个错误
window.onerror这样的catch-all事件处理程序之外)是将它们包装在try/catch
语句中。对于异步错误,我们只需遵循如何将此数据传递回调用堆栈的约定
因此,要用这些知识回答您的问题:
Source.post抛出错误
如果我假设“抛出一个错误”,您的意思是“发生了一个错误”,那么在不知道source.post的源代码的情况下,我们无法知道这将如何进行。如果确实抛出了一个错误,比如说出现了一些意外的ReferenceError
,那么实际上根本不会处理它:
function post() {
foo.bar; // will throw
}
function run() {
post()
.then(log)
.catch(log);
}
将导致:
ReferenceError: foo is not defined
at post (sync.js:6:3)
at run (sync.js:10:3)
at Object.<anonymous> (sync.js:15:1)
导致
捕获错误:foo
更有趣的是,您的代码在catch
语句中实际上抛出了一个新的Error
对象。在这种情况下,我们还有最后一件事需要了解。我们知道同步抛出一个错误意味着必须捕获它,但是从然后函数中抛出一个错误会导致一个被拒绝的异常,而不是一个错误,那么发生了什么呢?好的,promise实现在内部将传递给然后的函数包装在try/catch
块中,然后通过拒绝promise来处理此错误。我们可以这样证明:
function post() {
return new Promise((resolve, reject) => {
resolve('foo');
});
}
function run() {
post()
.then((result) => {
throw result;
})
.catch((err) => {
console.error('Caught error:', err);
});
}
在这种情况下,也会捕获错误
postActionCreator随后抛出一个错误
这现在变得很简单。捕获并传播中的错误,然后。它到达postActionCreator
内的catch
,然后返回到外部catch
handlePost会抛出一个错误
最简单的情况。它将在内部捕获,然后在之后立即在catch
语句中得到错误
最后,您可能会想,“如何处理Source.post
中的同步错误?如果这不是我的功能呢?”。好问题!您可以使用Bluebird之类的实用程序为您包装此函数。使用承诺时,函数应执行以下三项操作之一:
返回一个值
还愿
出错
对于这个问题,我们不太关心前两个案例,但您可以在这里阅读更多信息。让我们来看看这个错误的例子。
在JavaScript中,错误——就像大多数事情一样——只是对象。创建错误和选择如何传播错误是两件不同的事情。传播错误的两大类是同步和异步的。要同步传播错误,您必须抛出它,对于async,您只需通过一些预定义的约定(例如回调或承诺)传递错误对象
为了充分回答这个问题,我们需要了解如何处理这两种不同的错误类型。对于同步错误(已抛出),处理它们的唯一方法(除了像window.onerror这样的catch-all事件处理程序之外)是将它们包装在try/catch
语句中。对于异步错误,我们只需遵循如何将此数据传递回调用堆栈的约定
因此,要用这些知识回答您的问题:
Source.post抛出错误
如果我假设“抛出一个错误”,您的意思是“发生了一个错误”,那么在不知道source.post的源代码的情况下,我们无法知道这将如何进行。如果确实抛出了一个错误,比如说出现了一些意外的ReferenceError
,那么实际上根本不会处理它:
function post() {
foo.bar; // will throw
}
function run() {
post()
.then(log)
.catch(log);
}
将导致:
ReferenceError: foo is not defined
at post (sync.js:6:3)
at run (sync.js:10:3)
at Object.<anonymous> (sync.js:15:1)
导致
捕获错误:foo
更有趣的是,您的代码在catch
语句中实际上抛出了一个新的Error
对象。在这种情况下,我们还有最后一件事需要了解。我们知道同步抛出一个错误意味着必须捕获它,但是从然后函数中抛出一个错误会导致一个被拒绝的异常,而不是一个错误,那么发生了什么呢?promise实现在内部将传递给的函数包装到try/catch
块中,然后处理此错误