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

时间:2016-01-25 03:40:24

标签: javascript node.js exception asynchronous 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();

我预测,例如每次发出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

请注意,当d调用reject()时,我预测处理会转到c错误回调。同样,c reject()会转到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

c拒绝()似乎转到a 结果回调。

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

问题:

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

1 个答案:

答案 0 :(得分:5)

基本问题是,您执行了c();而不是return c();,其他问题包括:

  • 方法dc可以简化,停止包装承诺 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();