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

时间:2022-10-28 13:22:24

So, I want my first level catch to be the one that handles the error. Is there anyway to propagate my error up to that first catch?

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

Reference code, not working (yet):

参考代码,但尚未运行:

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

5 个解决方案

#1


12  

With the new async/await syntax you can achieve this. Please note that at the moment of writing this is not supported by all browsers, you probably need to transpile your code with babel (or something similar).

使用新的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);
  }
}

#2


19  

You cannot use try-catch statements to handle exceptions thrown asynchronously, as the function has "returned" before any exception is thrown. You should instead use the promise.then and promise.catch methods, which represent the asynchronous equivalent of the try-catch statement.

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

What you need to do is to return the promise, then chain another .catch to it:

你需要做的是返回承诺,然后将另一个.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);
});

Promises are chainable, so if a promise rethrows an error, it will be delegated down to the next .catch.

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

By the way, you don't need to use parentheses around throw statements (throw a is the same as throw(a)).

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


If you're running this code in Node.js and for some reason you're not allowed to edit the promise function, you can use domains to do so. Note that domains aren't exactly the easiest of things to deal with and do have some annoying edge cases in certain circumstances. Unless you really have to, I'd highly recommend using promises instead.

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

#3


4  

No! That's completely impossible, as promises are inherently asynchronous. The try-catch clause will have finished execution when the exception is thrown (and time travel still will not have been invented).

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

Instead, return promises from all your functions, and hook an error handler on them.

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

#4


2  

I often find the need to ensure a Promise is returned and almost as often needing to handle a local error and then optionally rethrow it.

我经常发现需要确保返回Promise,并且几乎经常需要处理本地错误然后可选地重新抛出它。

function doSomeWork() {
  return Promise.try(function() {

    return request.get(url).then(function(response) {
      // ... do some specific work
    });

  }).catch(function(err) {
    console.log("Some specific work failed", err);
    throw err; // IMPORTANT! throw unless you intend to suppress the error
  });
}

The benefit of this technique (Promise.try/catch) is that you start/ensure a Promise chain without the resolve/reject requirement which can easily be missed and create a debugging nightmare.

这种技术(Promise.try / catch)的好处是你可以启动/确保一个没有解决/拒绝要求的Promise链,这很容易被错过,并产生调试噩梦。

#5


0  

To expand on edo's answer, if you want to catch the errors of an async function that you don't want to wait for. You can add an await statement at the end of your function.

要扩展edo的答案,如果你想捕获一个你不想等待的异步函数的错误。您可以在函数末尾添加await语句。

async function() {
  try {
    const asyncResult = someAsyncAction();

    // "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);

    await asyncResult;
  } catch (error) {
    console.error(error);
  }
}

If someAsyncAction fails the catch statement will handle it.

如果someAsyncAction失败,catch语句将处理它。

#1


12  

With the new async/await syntax you can achieve this. Please note that at the moment of writing this is not supported by all browsers, you probably need to transpile your code with babel (or something similar).

使用新的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);
  }
}

#2


19  

You cannot use try-catch statements to handle exceptions thrown asynchronously, as the function has "returned" before any exception is thrown. You should instead use the promise.then and promise.catch methods, which represent the asynchronous equivalent of the try-catch statement.

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

What you need to do is to return the promise, then chain another .catch to it:

你需要做的是返回承诺,然后将另一个.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);
});

Promises are chainable, so if a promise rethrows an error, it will be delegated down to the next .catch.

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

By the way, you don't need to use parentheses around throw statements (throw a is the same as throw(a)).

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


If you're running this code in Node.js and for some reason you're not allowed to edit the promise function, you can use domains to do so. Note that domains aren't exactly the easiest of things to deal with and do have some annoying edge cases in certain circumstances. Unless you really have to, I'd highly recommend using promises instead.

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

#3


4  

No! That's completely impossible, as promises are inherently asynchronous. The try-catch clause will have finished execution when the exception is thrown (and time travel still will not have been invented).

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

Instead, return promises from all your functions, and hook an error handler on them.

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

#4


2  

I often find the need to ensure a Promise is returned and almost as often needing to handle a local error and then optionally rethrow it.

我经常发现需要确保返回Promise,并且几乎经常需要处理本地错误然后可选地重新抛出它。

function doSomeWork() {
  return Promise.try(function() {

    return request.get(url).then(function(response) {
      // ... do some specific work
    });

  }).catch(function(err) {
    console.log("Some specific work failed", err);
    throw err; // IMPORTANT! throw unless you intend to suppress the error
  });
}

The benefit of this technique (Promise.try/catch) is that you start/ensure a Promise chain without the resolve/reject requirement which can easily be missed and create a debugging nightmare.

这种技术(Promise.try / catch)的好处是你可以启动/确保一个没有解决/拒绝要求的Promise链,这很容易被错过,并产生调试噩梦。

#5


0  

To expand on edo's answer, if you want to catch the errors of an async function that you don't want to wait for. You can add an await statement at the end of your function.

要扩展edo的答案,如果你想捕获一个你不想等待的异步函数的错误。您可以在函数末尾添加await语句。

async function() {
  try {
    const asyncResult = someAsyncAction();

    // "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);

    await asyncResult;
  } catch (error) {
    console.error(error);
  }
}

If someAsyncAction fails the catch statement will handle it.

如果someAsyncAction失败,catch语句将处理它。