【问题标题】:Try... Catch in async await not catching error [duplicate]尝试...在异步等待中捕获未捕获错误[重复]
【发布时间】:2018-04-20 04:28:48
【问题描述】:

为什么 try...catch 不适用于以下示例代码?

const http2 = require("http2")
const url = require("url")


function sendRequest() {
    return new Promise((resolve, reject) => {

        var r = http2.request({
            "host": "www.google.com",
            "method": "GET",
            "path": "/"
        }, (resp) => {
            var data = []
            resp.on("data", (chunk) => {
                throw ("Error")
            })
            resp.on("end", () => {
                console.log("ended")
                resolve("finished")
            })
            resp.on("error", (e) => {
                console.log("error")
                reject(e)
            })
        })
        r.end()
    })
}

async function wrapper(){
    try {
        console.log("Sending request")
        await sendRequest()
        console.log("Finished sending Request")
    }catch(e){
        console.log("error!") // Supposed to see this
        console.log(e)
    }
    console.log("All finished") // Supposed to see this
}

wrapper()

输出如下:

Sending request

/Users/test-user/test.js:15
                throw ("Error")
                ^
Error

Process finished with exit code 1

【问题讨论】:

  • 这里的问题不是等待,而是你的承诺......你抛出错误,而不是调用拒绝。
  • 为什么data首先是一个错误?

标签: javascript node.js


【解决方案1】:

你可以在一个 Promise 中 throw 并使用 catch 捕获错误,只要错误在 Promise 本身而不是在不同的异步回调中。

例如,test() 按预期工作,但 test2() 不能:

function test(){
    return new Promise((resolve, reject) => {
        throw (new Error("error"))
    })
}

function test2(){
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            throw (new Error("error"))
        }, 100)

    })
}
async function go (){
    try {
        await test()
    } catch(err){
        console.log("caught error from test(): ", err.message)
    }

    try {
        await test2()
    } catch(err){
        console.log("caught error from test2(): ", err.message)
    }

}
go()

这两种情况都适用于 reject() 而不是 throw()

【讨论】:

    【解决方案2】:

    因为throw 仅在async 函数中转换为promise 拒绝,所以promise 执行器的同步 部分(您传递new Promise 的回调),或 thencatch 回调的同步部分。您在非async 回调中执行此操作,而这些地方都不是。

    throw ("Error"); 应该是 reject("Error");(嗯,真的应该是 reject(new Error("Error")); - 拒绝是错误,所以使用 new Error 会为您提供堆栈跟踪等)。


    旁注:通常情况下,接收data 事件在任何情况下都不会是错误...

    旁注 2:throw ("Error"); 中的 () 什么都不做。当投掷是一种选择时,只需throw "Error";(或者,再次,throw new Error("Error");)。

    【讨论】:

    • 在块上有错误,可能并不完全奇怪。例如,如果说下载一个文件并且您希望收到一个 ZIP,您可以检查前几个块中的魔术代码,然后中止并拒绝承诺。无需下载您不喜欢的内容。
    • @Keith:当然。但是有问题的代码是无条件的。
    • 我认为问题中的代码不是真的.. :)
    猜你喜欢
    • 2014-12-01
    • 1970-01-01
    • 2019-10-20
    • 2019-02-11
    • 2020-08-06
    • 2020-05-31
    • 2021-06-10
    • 2021-05-05
    • 2020-09-12
    相关资源
    最近更新 更多