从嵌套的 async/await 函数中捕获错误
Posted
技术标签:
【中文标题】从嵌套的 async/await 函数中捕获错误【英文标题】:Catching errors from nested async/await functions 【发布时间】:2017-04-12 11:15:46 【问题描述】:我在 node 4.3
脚本中有一个函数链,看起来像回调 -> 承诺 -> async/await -> async/await -> async/await
像这样:
const topLevel = (resolve, reject) =>
const foo = doThing(data)
.then(results =>
resolve(results)
)
.catch(err =>
reject(err)
)
async function doThing(data)
const thing = await doAnotherThing(data)
return thing
async function doAnotherThing(data)
const thingDone = await etcFunction(data)
return thingDone
(之所以没有一路async/await
是因为顶层函数是一个任务队列库,表面上不能运行async/await
风格)
如果etcFunction()
抛出,error
是否会一直冒泡到顶层Promise
?
如果没有,我该如何冒泡errors
?我需要像这样将每个await
包装在try/catch
和throw
中吗?
async function doAnotherThing(data)
try
await etcFunction(data)
catch(err)
throw err
【问题讨论】:
什么是makePromise
?
"顶层函数是一个任务队列库,表面上不能以异步/等待方式运行" - 队列库没有理由不能使用async function
s 作为任务。你真的不应该处理回调。如果您需要使用采用回调样式的特定队列库,请使用包装函数。
@Bergi makePromise
实际上是一个 async
函数,但由于它是从非async
环境调用的,所以我将其视为承诺。回复:我同意,我最终会尝试并承诺它,但我可以同时有可靠的错误冒泡吗?
@Bergi 我从 sn-p 中删除了makePromise
位以澄清——顶层调用的第一个函数是async function
,我将其视为常规Promise
@Bergi 是的,感谢您发现该错误和其他错误-我应该只是复制实际代码而不是尝试用伪代码重新创建
【参考方案1】:
如果
etcFunction()
抛出,错误会一直冒泡到async function
s 吗?
是的。最外层函数返回的承诺将被拒绝。不需要try … catch(e) throw e;
,这就像在同步代码中一样毫无意义。
...一直冒泡到最顶层的 Promise?
没有。您的 topLevel
包含多个错误。如果您不从then
回调中return
doThing(data)
,它将被忽略(甚至不等待)并且拒绝保持未处理状态。你必须使用
.then(data => return doThing(data); )
// or
.then(data => doThing(data))
// or just
.then(doThing) // recommended
一般来说,你的函数应该是这样的:
function toplevel(onsuccess, onerror)
makePromise()
.then(doThing)
.then(onsuccess, onerror);
没有不必要的函数表达式,没有.then(…).catch(…)
antipattern(这可能导致onsuccess
和onerror
都被调用)。
【讨论】:
【参考方案2】:我知道这个问题很老,但是正如你的问题所写的那样,doAnotherThing()
函数不是不必要的,因为它只是包装了etcFunction()
?
所以你的代码可以简化为:
async function topLevel()
let thing = await doThing(data)
let thingDone = await etcFunction(data)
//Everything is done here...
//Everything starts here...
topLevel()
【讨论】:
我认为这是演示嵌套等待调用的模拟代码【参考方案3】:我刚刚遇到了一个类似的问题,我的嵌套错误似乎没有冒泡到我的***函数。
对我来说,解决方法是从我的嵌套函数中删除“try/catch”并允许抛出错误。
【讨论】:
以上是关于从嵌套的 async/await 函数中捕获错误的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 async/await 编写 .then 函数,以便捕获来自 axios 的响应(在单独的文件和方法中,在 vue 中)