复杂承诺返回链中的 promise catch() 顺序
Promise catch() order in complex promise return chain
当我将一个承诺从函数 A 返回给函数 B 时,从 A 返回数据,并且两个调用都抓住了 Promise?我知道,当承诺被解决时,A总是首先被执行,然后是B,然后是A返回的数据。但是我无法理解错误是如何被抓住的,当这种承诺的回归形成一条长长的链条时。下面是该方案的简化示例。我正在使用 Redux-thunk 动作创建者来管理状态。
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's 然后抛出一个错误
- 然后 handlePost 抛出错误
使用 promise 时,函数应执行以下三项操作之一:
- 返回一个值
- 返回承诺
- 抛出错误
对于这个问题,我们不太关心前两种情况,但您可以在此处阅读有关承诺解决程序的信息以获取更多信息。因此,让我们看一下该错误案例。
在 JavaScript 中,错误 - 像大多数事情一样 - 只是对象。创建错误和选择如何传播该错误是两回事。传播错误的两大类是同步和异步。要同步传播错误,您必须throw
它,对于异步,您只需通过一些预定义的约定(例如回调或承诺(传递错误对象。
要完全回答这个问题,我们需要了解如何处理这两种不同的错误类型。对于同步错误(已抛出的错误(,处理它们的唯一方法(除了像 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)
现在,如果 post
函数实际上异步处理错误,在这种情况下,通过确认传递错误的 promise 约定,我们会看到它会被捕获:
function post() {
return new Promise((resolve, reject) => {
reject('foo');
});
}
function run() {
post()
.then(() => {})
.catch((err) => {
console.error('Caught error:', err);
});
}
结果在
Caught error: foo
更有趣的部分是,您的代码在 catch
语句中实际上抛出了一个新的Error
对象。在这种情况下,我们还有最后一件事要了解。我们知道,同步抛出错误意味着必须捕获它,但是从then
函数中抛出错误会导致拒绝异常,而不是错误,那么这是怎么回事呢?好吧,promise 实现是在内部将您传递给 then
的函数包装在一个 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's 然后抛出一个错误
现在这变得很简单。捕获并传播then
中的错误。它到达postActionCreator
内的catch
,然后被重新抛到外面catch
。
然后 handlePost 抛出错误
最简单的情况。它将在内部捕获,您将在then
后立即在 catch
语句中收到错误。
最后,您可能会想,"我如何处理Source.post
中的这些同步错误?如果这不是我的职能怎么办?问得好!您可以使用像 promise.try 这样的实用程序 从 Bluebird 为你包装这个函数。
- 节点Js:How to catch a“;没有这样的文件或目录“;读取线模块出错
- ajax请求的顺序总是不同的
- 按照选项卡索引的顺序循环一个jQuery选择
- 匹配一个单词,其中候选人可以跨越顺序组(跨度)
- 按顺序添加和删除类
- 按我自己的类克隆另一个元素的内容和顺序
- Javascript-根据赋值顺序,按键合并对象数组
- 2个backbone.js集合,具有相同的模型,但排序顺序不同
- querySelector/getElementByClassName嵌套项的顺序
- 以不同的顺序输出数据
- 重新排列HTML元素的顺序并更改内容
- errors with Javascript try catch
- 在Javascript中列出顺序子集元素
- 是否“;对于的“;循环迭代遵循JavaScript中的数组顺序
- Mongodb$in以与数组中相同的顺序获取结果
- 如何使用phonegap从安卓设备中提取联系人的字母顺序
- 在表单OnChange中交换数字顺序
- 如何按对象反转Angular ngRepeat的顺序's键,这些键是数字键
- 如何使用(this)访问Angular 2 http rxjs catch函数中的对象属性
- 复杂承诺返回链中的 promise catch() 顺序