为什么这个JavaScript Promise reject()会在结果回调中得到处理?

Bal*_*gle 1 javascript asynchronous exception node.js promise

这是更多代码的子集; Node.js中的JavaScript 实质上,等效于函数a调用某些单元测试(在函数中b).返回时b,a调用异常测试(在函数中c).c调用同步异常测试(在函数中d).稍后,c将调用另一个函数(e比方说)进行异步异常测试(Promise reject()用法).似乎最好在Node.js中使用Promise,但即使使用它们也不总是导致我预测的行为.

'use strict';

function d() {
  return new Promise(function(resolve, reject) {
    console.log('start d   throw test');
    try {
      throw new Error('Error type');
    } catch (e) {
      console.log('d catch block   e.message=' + e.message +
        '   rejecting   to c');
      return reject(new Error('d   ' + e.message));
    } // catch
  }) // Promise
}

function c() {
  return new Promise(function(resolve, reject) {
    console.log('start c');
    d()
    .then( // d then
      function(result) { console.log('c   d result callback'); },
      function(error) {
        console.log('c   d error callback   error.message=' + error.message +
          '   rejecting   to a');
        return reject(new Error('second try'));
      }
    ) // d then
  }) // Promise
}

function b() {
  console.log('start b   resolving   to a');
  return Promise.resolve();
}

function a() {
  return new Promise(function(resolve, reject) {
    console.log('start a');
    b()
    .then( // b then
      function(result) {
        console.log('a   b result callback   to c');
        c();
      },
      function(error) { 
        console.log('a   b error callback   error.message=' + error.message);
      }
    ) // b then
    .then( // c then
      function(result) { 
        console.log('a   c result callback   ');
      },
      function(error) {
        console.log('a   c error callback   error.message=' + error.message);
      }
    ) // c then
    .catch(
      function(error) {
        console.log('a   final catch   error.message=' + error.message);
      }
    ) // catch
  }) // Promise
}

a();
Run Code Online (Sandbox Code Playgroud)

我预测,例如,每次我发出Promise reject()时,都会在调用者的错误回调中进行处理.(注意,每个reject()也使用new Error.)因此,我期望在console.log中输出此输出.

start a
start b   resolving   to a
a   b result callback   to c
start c
start d   throw test
d catch block   e.message=Error type   rejecting   to c
c   d error callback   error.message=d   Error type   rejecting   to a
a   c error callback   error.message=second try
Run Code Online (Sandbox Code Playgroud)

请注意,当d调用reject()时,我预测处理会转到c错误回调.类似地,creject()将转到a错误回调.相反,我得到这个输出:

start a
start b   resolving   to a
a   b result callback   to c
start c
start d   throw test
d catch block   e.message=Error type   rejecting   to c
c   d error callback   error.message=d   Error type   rejecting   to a
a   c result callback
Run Code Online (Sandbox Code Playgroud)

c拒绝(),似乎是想给a 结果的回调.

可能涉及功能b; 如果我把它写出程序,我会得到理想的处理.这在这里很棒,但在更大的代码中,它是没有选择的.

问题:

  1. 为什么处理转到结果回调而不是错误回调?
  2. 功能b如何在完成后很长时间内产生效果?
  3. 我怎样才能解决这个问题?
  4. 使用return rejectreject单独相关的优点和缺点是什么?大多数时候(至少),它似乎有效.我没有抓到造成问题的较短形式.

mid*_*ido 5

基本问题是,你做c();return c();,而不是,其他问题包括:

  • 方法d,c可以被简化,停止包装承诺new Promise(...)
  • 避免使用.then(success, error),大多数情况下,更难以使用then(success).catch(error).
  • 你的代码可以简化为:

    'use strict';
    
    function d() {
      return Promise.reject(new Error('Error type'));
    }
    
    function c() {
      console.log('start c');
      return d()
        .then( result => console.log('c   d result callback'))
        .catch( error => {
          console.log('c   d error callback   error.message=' + error.message +
            '   rejecting   to a');
          throw new Error('second try');
        });
    }
    
    function b() {
      console.log('start b   resolving   to a');
      return Promise.resolve();
    }
    
    function a() {
        console.log('start a');
      return b()
        .then(result => {
          console.log('a   b result callback   to c');
          return c();      
        }).catch(error => console.log('a   b error callback   error.message=' + error.message))
        .then(result => console.log('a   c result callback   '))
        .catch(error => console.log('a   final catch   error.message=' + error.message));
    }
    
    a();
    
    Run Code Online (Sandbox Code Playgroud)