Promises链接:在创建Promise时添加错误处理程序vs添加到具有promise的变量

时间:2022-12-13 04:30:59
function getPromise() {
    return new Promise((resolve, reject) => {
        setTimeout(reject, 2000, new Error('fail'));
    });
}

const promise1 = getPromise();
promise1.catch(() => {
    // NOP
});

promise1
    .then(() => console.log('then promise1'))
    .catch(() => console.error('catch promise1'));

const promise2 = getPromise().catch(() => {
    // NOP
});

promise2
    .then(() => console.log('then promise2'))
    .catch(() => console.error('catch promise2'));

Output

catch promise1
then promise2

Explanations

Here promise2 will be processed differently then promise1. While promise1 will be rejected with 'fail' error, promise2 will be resolved with undefined.

这里promise2的处理方式与promise1不同。虽然promise1将因“失败”错误而被拒绝,但promise2将使用undefined解决。

My environment

Ubuntu 14.04, Node.js 10.1.0

Ubuntu 14.04,Node.js 10.1.0

Question

I think this behavior is not obvious. Why does the code work this way?

我认为这种行为并不明显。为什么代码以这种方式工作?

2 个解决方案

#1


2  

Because you chain the second then not to the rejecting promise, but to the promise returned by catch, which will resolve to whatever you return from the catch handler.

因为你链接第二个然后不是拒绝承诺,而是链接返回的promise,它将解析为你从catch处理程序返回的任何内容。

 Promise(promise1)
  -❎-> catch
  -✔-> then -❎- > catch
  -❎-----------------^

Promise
  -❎-> catch(promise2)
           -✔-> then -❎-> catch
           -❎-----------------^
  -✔------------^

In the first case, the promise rejects, so it will enter the catch directly assigned to it, and it will skip the then, going directly to the chained catch. In the second case, the promise rejects and the catch will be executed, but then it seems to handle the error, so the chained then will be called. If you don't want that, the catch has to rethrow the error, then the then will be skipped and it also enters the chained catch.

在第一种情况下,promise拒绝,因此它将进入直接分配给它的catch,它将跳过then,直接转到链接catch。在第二种情况下,promise拒绝并且catch将被执行,但是它似乎处理错误,因此将链接然后被调用。如果您不想这样,catch必须重新抛出错误,然后将跳过then,它也会进入链式catch。

#2


2  

Catch returns a new promise:

Catch返回一个新的承诺:

let orig = Promise.reject("fail")
let p = orig.catch(console.log)

console.log("is p the same as orig? ", p === orig)

p.then(() => console.log('p is a promise?', p instanceof Promise))

So when you call

所以当你打电话

 const promise2 = getPromise().catch(() => { //..})

and assign the value to a promise2 that is a brand new promise returned from catch. In the first case you use the oringal promise1 in both statements.

并将值赋给promise2,这是一个从catch返回的全新承诺。在第一种情况下,您在两个语句中使用oringal promise1。

To make the first statement work like the second, you would need to do something like:

要使第一个语句像第二个语句一样工作,您需要执行以下操作:

function getPromise() {
    return new Promise((resolve, reject) => {
        setTimeout(reject, 2000, new Error('fail'));
    });
}

let promise1 = getPromise();

// reassign the value of promise1
promise1 = promise1.catch(() => {
    // NOP
});

promise1
    .then(() => console.log('then promise1'))
    .catch(() => console.error('catch promise1'));
Which is also the equivalent of just doing:

promise1
  .catch(() => {/* noop */ })
  .then(() => console.log('then promise1'))
  .catch(() => console.error('catch promise1'));

Also, if you want to make sure the error is passed down the chain, you can always return a rejected promise from catch:

此外,如果您想确保错误传递到链中,您始终可以从catch返回被拒绝的承诺:

let promise1 = getPromise().catch((e) => {
    return Promise.reject(e)
});

#1


2  

Because you chain the second then not to the rejecting promise, but to the promise returned by catch, which will resolve to whatever you return from the catch handler.

因为你链接第二个然后不是拒绝承诺,而是链接返回的promise,它将解析为你从catch处理程序返回的任何内容。

 Promise(promise1)
  -❎-> catch
  -✔-> then -❎- > catch
  -❎-----------------^

Promise
  -❎-> catch(promise2)
           -✔-> then -❎-> catch
           -❎-----------------^
  -✔------------^

In the first case, the promise rejects, so it will enter the catch directly assigned to it, and it will skip the then, going directly to the chained catch. In the second case, the promise rejects and the catch will be executed, but then it seems to handle the error, so the chained then will be called. If you don't want that, the catch has to rethrow the error, then the then will be skipped and it also enters the chained catch.

在第一种情况下,promise拒绝,因此它将进入直接分配给它的catch,它将跳过then,直接转到链接catch。在第二种情况下,promise拒绝并且catch将被执行,但是它似乎处理错误,因此将链接然后被调用。如果您不想这样,catch必须重新抛出错误,然后将跳过then,它也会进入链式catch。

#2


2  

Catch returns a new promise:

Catch返回一个新的承诺:

let orig = Promise.reject("fail")
let p = orig.catch(console.log)

console.log("is p the same as orig? ", p === orig)

p.then(() => console.log('p is a promise?', p instanceof Promise))

So when you call

所以当你打电话

 const promise2 = getPromise().catch(() => { //..})

and assign the value to a promise2 that is a brand new promise returned from catch. In the first case you use the oringal promise1 in both statements.

并将值赋给promise2,这是一个从catch返回的全新承诺。在第一种情况下,您在两个语句中使用oringal promise1。

To make the first statement work like the second, you would need to do something like:

要使第一个语句像第二个语句一样工作,您需要执行以下操作:

function getPromise() {
    return new Promise((resolve, reject) => {
        setTimeout(reject, 2000, new Error('fail'));
    });
}

let promise1 = getPromise();

// reassign the value of promise1
promise1 = promise1.catch(() => {
    // NOP
});

promise1
    .then(() => console.log('then promise1'))
    .catch(() => console.error('catch promise1'));
Which is also the equivalent of just doing:

promise1
  .catch(() => {/* noop */ })
  .then(() => console.log('then promise1'))
  .catch(() => console.error('catch promise1'));

Also, if you want to make sure the error is passed down the chain, you can always return a rejected promise from catch:

此外,如果您想确保错误传递到链中,您始终可以从catch返回被拒绝的承诺:

let promise1 = getPromise().catch((e) => {
    return Promise.reject(e)
});