【问题标题】:Why does this JavaScript Promise reject() get processed at the result callback?为什么这个 JavaScript Promise reject() 在结果回调中得到处理?
【发布时间】:2023-03-18 12:02:01
【问题描述】:

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

'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 错误回调。同样,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

creject() 似乎要转到a result 回调。

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

问题:

  1. 为什么处理转到结果回调而不是错误回调?
  2. 函数 b 完成这么长时间后如何产生效果?
  3. 我该如何解决这个问题?
  4. 使用return reject 与单独使用reject 有哪些优点和缺点?大多数时候(至少),它似乎工作。我没有发现导致问题的较短形式。

【问题讨论】:

  • 必须是return c();
  • 一个非常有趣的阅读:pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html 你犯了 Rookie 错误 #5,你没有返回 c()。另外,不要混用太多,要么使用错误回调,要么(重新)抛出错误(强烈建议抛出),不能同时使用,这很混乱。
  • @ShanShan:感谢你激励我重读那篇文章。这是我看过的关于 Promises 的最好的文章之一。我之前(显然)没有完全掌握新秀错误#5。

标签: javascript node.js exception asynchronous promise


【解决方案1】:

基本问题是,您使用的是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();
    

【讨论】:

  • 非常感谢。你帮了我两个大忙。 (1) 您确定了“return c()”问题。 (2) 你演示了很多我没见过的替代语法。 (我并没有忘记你的代码比我的要短得多而且非常清晰!)
猜你喜欢
  • 1970-01-01
  • 2018-10-10
  • 1970-01-01
  • 2021-01-11
  • 1970-01-01
  • 2015-07-15
  • 1970-01-01
  • 2021-06-24
  • 1970-01-01
相关资源
最近更新 更多