使用First Level try ... catch捕获JavaScript承诺中的错误

Kir*_*met 32 javascript node.js promise bluebird

所以,我希望我的第一级捕获是处理错误的那个.反正有没有将我的错误传播到第一次捕获?

参考代码,但尚未运行:

Promise = require('./framework/libraries/bluebird.js');

function promise() {
    var promise = new Promise(function(resolve, reject) {
        throw('Oh no!');
    });

    promise.catch(function(error) {
        throw(error);
    });
}

try {   
    promise();
}
// I WANT THIS CATCH TO CATCH THE ERROR THROWN IN THE PROMISE
catch(error) {
    console.log('Caught!', error);
}
Run Code Online (Sandbox Code Playgroud)

Qan*_*avy 33

您不能使用try-catch语句来处理异步抛出的异常,因为函数在抛出任何异常之前已"返​​回".您应该使用promise.thenpromise.catch方法,它们表示try-catch语句的异步等价物.

你需要做的是返回承诺,然后将另一个链接.catch到它:

function promise() {
    var promise = new Promise(function(resolve, reject) {
        throw('Oh no!');
    });

    return promise.catch(function(error) {
        throw(error);
    });
}

promise().catch(function(error) {
    console.log('Caught!', error);
});
Run Code Online (Sandbox Code Playgroud)

Promise是可链接的,因此如果一个promise重新出现错误,它将被委托给下一个.catch.

顺便说一下,你不需要在throw语句周围使用括号(与之throw a相同throw(a)).


如果您在Node.js中运行此代码,并且由于某种原因您不允许编辑该promise函数,则可以使用域来执行此操作.请注意,域并不是最容易处理的事情,并且在某些情况下确实存在一些恼人的边缘情况.除非你真的需要,否则我强烈推荐使用promises.

  • 对于它的价值,你绝对不应该在我的答案中使用这个方法而你应该使用promises.承诺已经解决了这个问题并提供了投掷安全性.你可以简单地省略`promise.catch`,事实上,上面的整个代码可以重构为`Promise.reject("哦不")`(尽管你应该_always_拒绝错误).然后你可以做`Promise.reject("哦不").catch(function(e){console.log(e);});``记录"哦不".事实上,投掷安全性是承诺与可链接性和可组合性之间最重要的卖点之一. (2认同)

Edo*_*Edo 24

使用新的async/await语法,您可以实现此目的.请注意,在撰写本文时,并非所有浏览器都支持此操作,您可能需要使用babel(或类似的东西)来转换代码.

// Because of the "async" keyword here, calling getSomeValue()
// will return a promise.
async function getSomeValue() {
  if (somethingIsNotOk) {
    throw new Error('uh oh');
  } else {
    return 'Yay!';
  }
}

async function() {
  try {
    // "await" will wait for the promise to resolve or reject
    // if it rejects, an error will be thrown, which you can
    // catch with a regular try/catch block
    const someValue = await getSomeValue();
    doSomethingWith(someValue);
  } catch (error) {
    console.error(error);
  }
}
Run Code Online (Sandbox Code Playgroud)

  • @ItsmeJulian这取决于您要如何处理它。如果您只想在catch中记录日志,则无需冒犯错误。另外,我想如果您想冒泡的话,我更喜欢在catch里面扔`err`。 (2认同)

Ber*_*rgi 5

没有!这是完全不可能的,因为承诺本质上是异步的.抛出异常时,try-catch子句将完成执行(并且仍然不会发明时间旅行).

相反,从所有函数返回promise,并在它们上挂钩错误处理程序.