Node.js 为什么在这个NodeJS异步函数中没有捕捉到错误?

Node.js 为什么在这个NodeJS异步函数中没有捕捉到错误?,node.js,error-handling,promise,async-await,Node.js,Error Handling,Promise,Async Await,我试图理解为什么upload函数中的catch块没有捕获createReleaseVersion函数中请求(…)行之后抛出的异常。 nodejs脚本崩溃,异常未处理。控制台中只显示异常的错误 在下面的代码中,我希望打印“got you”然后打印“after”,但这并没有发生 如果我将throw替换为return-reject(…相同的对象),那么我将获得所需的输出。 我先印上“抓住你”然后印上“之后” function createReleaseVersion(releaseVersion) {

我试图理解为什么upload函数中的catch块没有捕获createReleaseVersion函数中请求(…)行之后抛出的异常。 nodejs脚本崩溃,异常未处理。控制台中只显示异常的错误

在下面的代码中,我希望打印“got you”然后打印“after”,但这并没有发生

如果我将throw替换为return-reject(…相同的对象),那么我将获得所需的输出。
我先印上“抓住你”然后印上“之后”

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');

<好吧,让我们用一个更简单的例子:

new Promise((resolve, reject) => {
  setTimeout(() => { throw new Error(); });
});
这会使整个过程崩溃。原因是
setTimeout
(或者在您的情况下是
request
)预订了稍后调用的回调

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

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

try {
   executor(resolve, reject); // your code
} catch (e) {
   reject(e);
}
因为在您的情况下,函数不会同步执行——它无法了解异常的上下文。这在将来可能会随着分区而改变,但可能不会

如果要在promisified函数中标记错误,可以调用第二个参数(
reject
)和
reject(newerror(…)

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


我也建议您只拒绝使用代码>错误< /Cord>对象以获得更好的堆栈跟踪。

,让我们采取一个更简单的例子:

new Promise((resolve, reject) => {
  setTimeout(() => { throw new Error(); });
});
这会使整个过程崩溃。原因是
setTimeout
(或者在您的情况下是
request
)预订了稍后调用的回调

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

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

try {
   executor(resolve, reject); // your code
} catch (e) {
   reject(e);
}
因为在您的情况下,函数不会同步执行——它无法了解异常的上下文。这在将来可能会随着分区而改变,但可能不会

如果要在promisified函数中标记错误,可以调用第二个参数(
reject
)和
reject(newerror(…)

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


我还建议您仅拒绝带有
错误的
对象,以获得更好的堆栈跟踪。

谢谢您的回答。关于您编写的“如果您想在promisified函数中标记错误-您可以调用第二个参数(reject)和reject(new error(…)”,还有一个问题。你能提供更多的细节吗?我怎样才能做到这一点。您的意思是将请求调用包装在resolve中吗?当然:
new Promise((resolve,reject)=>setTimeout(()=>reject(new Error()))
将创建一个被拒绝的承诺-这不是抛出新错误,它在那里不起作用。谢谢你的回答。还有一个关于你所写内容的问题“如果你想在promisified函数中标记一个错误-你可以调用第二个参数(拒绝)和拒绝(新错误(…)“。您能提供更多详细信息吗?我该如何实现该方法。您的意思是将请求调用封装在resolve中吗?当然:
new Promise((resolve,reject)=>setTimeout(()=>reject(new Error())
将创建一个被拒绝的承诺-而不是
抛出新错误
,这在那里不起作用。相关问题和答案:(认为它有用-但不是真正的副本)相关问题和答案:(认为它有用-但不是真正的副本)