【问题标题】:Skipping loop iteration after catch Javascript捕获 Javascript 后跳过循环迭代
【发布时间】:2020-09-21 13:18:56
【问题描述】:

我正在构建一个 API,它需要循环调用另一个 API(特别是 Quickbooks Online)。这些调用包含在一个 Promise 中,该 Promise 会根据 Quickbooks 返回的内容来解决或拒绝。一切正常,但是,我希望能够在捕获错误后继续循环。目前,一个错误被捕获并记录到数据库中,但循环停止并且不再进行调用。我在 catch 块中尝试了“返回”和“继续”,但无济于事。

代码示例:

// This is part of a larger loop. Needs to be async
await paymentInfo.forEach(async ln => {

        var payRef = ln.payment_ref
        var vendor = ln.vendor_id

        var finalPayment = await service.createPayment(args)
          .then(console.log("Payment created"))
          .catch((err) => { 

            // Log error to DB
            service.dbUpdate(err)
            .then(console.log("Error Logged to DB"))
            .catch(() => {})

            // Continue??
       })
      // Database update here with payment ID
})

最终,在 catch 之后,我只想继续循环的下一次迭代。据我所知,没有一种简单的方法可以做到这一点。欢迎任何建议。

【问题讨论】:

    标签: javascript foreach promise async-await


    【解决方案1】:

    您已经使用async/await,因此无需使用.then。您可以只使用await 并使用常规try/catch 捕获错误,然后如果您将continue 放入for 中,continue 也将直观地工作。但是您似乎需要并行处理循环迭代,因此每次迭代都将在函数调用中进行,这意味着您可以return

    这里的另一个问题是您没有处理异步函数中的错误,因为它没有被等待。相反,您等待 forEach 什么都不返回。

    解决方法是将map 你的数组转换为一组承诺(执行匿名异步函数的结果),然后使用Promise.all 立即等待所有这些承诺。

    await Promise.all(paymentInfo.map(ln => (async () => {
    
            var payRef = ln.payment_ref
            var vendor = ln.vendor_id
    
            try {
                var finalPayment = await service.createPayment(args)
                console.log("Payment created")
            } catch (err) {
                // Log error to DB
                try {
                    await service.dbUpdate(err)
                    console.log("Error Logged to DB"))
                } catch (e) {}
    
               return
            }
    
           // Database update here with payment ID
    })())
    

    但是,如果唯一的原因是您想对未创建付款的可能性做出反应,那么您毕竟在这里需要continue,这对我来说似乎不合逻辑。在这种情况下,您只需无条件地使用付款值,因为如果抛出错误,它将跳过 try 块的其余部分!

    await Promise.all(paymentInfo.map((async ln => {
    
            var payRef = ln.payment_ref
            var vendor = ln.vendor_id
    
            try {
                var finalPayment = await service.createPayment(args)
                console.log("Payment created")
    
                // Database update here with payment ID
            } catch (err) {
                // Log error to DB
                try {
                    await service.dbUpdate(err)
                    console.log("Error Logged to DB"))
                } catch (e) {}
            }
    })())
    

    【讨论】:

    • 嗯,我明白你的意思了。曾经尝试过这样做。它现在打破了这个块并继续前进,但它似乎仍然没有尝试解决或拒绝数组中的所有承诺,它在第一个被拒绝后停止。
    • 这就是为什么您应该像我在示例中所做的那样在异步函数中构建错误处理。然后该函数的承诺将始终得到解决。或者,您可以查看 Promise.allSettled,但这是非常新的内容,可能还不适用于您的环境。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-23
    • 1970-01-01
    • 1970-01-01
    • 2021-11-15
    • 2019-05-17
    相关资源
    最近更新 更多