【问题标题】:Catching errors from nested async/await functions从嵌套的 async/await 函数中捕获错误
【发布时间】: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/catchthrow 中吗?

async function doAnotherThing(data) {
   try {
     await etcFunction(data)
   } catch(err) {
     throw err  
   }
}

【问题讨论】:

  • 什么是makePromise
  • "顶层函数是一个任务队列库,表面上不能以异步/等待方式运行" - 队列库没有理由不能使用async functions 作为任务。你真的不应该处理回调。如果您需要使用采用回调样式的特定队列库,请使用包装函数。
  • @Bergi makePromise 实际上是一个 async 函数,但由于它是从非async 环境调用的,所以我将其视为承诺。回复:我同意,我最终会尝试并承诺它,但我可以同时有可靠的错误冒泡吗?
  • @Bergi 我从 sn-p 中删除了makePromise 位以澄清——顶层调用的第一个函数是async function,我将其视为常规Promise
  • @Bergi 是的,感谢您发现该错误和其他错误-我应该只是复制实际代码而不是尝试用伪代码重新创建

标签: javascript node.js async-await ecmascript-2017


【解决方案1】:

如果etcFunction() 抛出,错误会一直冒泡到async functions 吗?

是的。最外层函数返回的承诺将被拒绝。不需要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(这可能导致onsuccessonerror被调用)。

【讨论】:

    【解决方案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”并允许抛出错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-13
      • 1970-01-01
      • 1970-01-01
      • 2021-08-06
      • 1970-01-01
      • 2016-02-07
      • 2020-06-02
      • 1970-01-01
      相关资源
      最近更新 更多