为什么在此NodeJS异步函数中未捕获错误?

时间:2018-07-03 12:23:49

标签: node.js error-handling promise async-await

我试图理解为什么上载函数中的catch块无法捕获createReleaseVersion函数中request(.....)行之后引发的异常。 nodejs脚本崩溃,并且未处理异常。控制台中仅显示异常错误。

在以下代码中,我希望先打印“先了解您然后再整理”,但这不会发生。

如果我用return return(...相同的对象)替换throw,那么我将得到所需的输出。 我先打印“得到你”,然后打印“之后”

function createReleaseVersion(releaseVersion) {
    var options = {
        uri: 'https://someurl',
        method: 'POST',
        json: {'version': releaseVersion}
    };

    return new Promise(function(resolve, reject) {
        request(options, function (error, response, body) {
            throw {
                error: error,
                response: response,
                body: body
            };
            console.log(body);
            if (error) {
                throw {
                    error: error,
                    response: response,
                    body: body
                };
            } else {
                resolve();
            }
        });
    });
}

async function upload(releaseVersion) {
    try {
        await createReleaseVersion(releaseVersion);
    } catch (error) {
        console.log('got you');
    }
    console.log('after');
}

upload('ddd');

1 个答案:

答案 0 :(得分:2)

好吧,我们来看一个简单的例子:

new Promise((resolve, reject) => {
  setTimeout(() => { throw new Error(); });
});

哪个使进程崩溃。原因是setTimeout(或您的情况下为request预订了一个回调,稍后将被调用

当最终调用回调时-promise构造函数已经执行完毕,并且错误被抛出到当前上下文(setTimeout / request的上下文)中。

promise构造函数同步捕获错误的原因是因为它基本上是这样做的:

try {
   executor(resolve, reject); // your code
} catch (e) {
   reject(e);
}

因为在您的情况下该函数无法同步执行-它没有办法了解异常的上下文。将来随着区域的变化可能会改变,但可能不会改变。

如果要在函数内部标记错误-可以调用第二个参数(rejectreject(new Error(...))

我热烈建议您使用util.promisify而不是将API手动转换为Promise,以避免此类问题:)

我还建议您仅拒绝使用Error对象,以获得更好的堆栈跟踪。