【问题标题】:Node.js: Unhandled promise rejection - UnhandledPromiseRejectionWarningNode.js:未处理的承诺拒绝 - UnhandledPromiseRejectionWarning
【发布时间】:2017-10-18 02:31:17
【问题描述】:

我有一个 Node.js 应用程序。这个应用程序有一个启动进程的按钮。该过程中的步骤返回承诺。我试图将这些承诺链接在一起。出于某种原因,我收到了UnhandledPromiseRejectionWarning。但是,在我看来,我已经正确设置了它。我的代码如下所示:

var myButton = document.getElementById('myButton');
if (myButton) {
  console.log('here');
  myButton.addEventListener('click', executeAction('0'));
}

function executeAction(input) {      
  let param1 = 'A';
  let promise = new Promise(function(resolve, reject) {
    try {
      executeStep1()
        .then(result => executeStep2(param1, result, input))
        .then(result => function(result) {
           console.log('All done');
           resolve(result);
        })
        .catch(err => reject(err))
      ;
    } catch (ex) {
      reject(ex);
    }
  });
  return promise;     
}

function executeStep1() {
  let promise = new Promise(function(resolve, reject) {        
    try {
      setTimeout(function() {
        resolve('[something]');
      }, 3000);
    } catch (ex) {
      reject();
    }
  });
  return promise;
}

function executeStep2(p1, p2, p3) {
  let promise = new Promise(function(resolve, reject) {        
    try {
      setTimeout(function() {
        console.log('step 2 has executed');
        resolve('awesome!')
      }, 3000);
    } catch (ex) {
      reject(ex);
    }  
  });
  return promise;
}

我已经确认executeStep2 函数运行完成。我基于这样一个事实,即我可以在控制台窗口中看到“第 2 步已执行”。然而,令我惊讶的是,我从未在控制台窗口中看到“全部完成”。相反,我看到了上面提到的UnhandledPromiseRejectionWarning。这个结果有两点我不明白:

  1. 为什么我在控制台中看不到“全部完成”?不应该在executeStep2 解决后执行该函数吗?
  2. 拒绝来自哪里?我没有看到任何拒绝这个的东西。

非常感谢您的帮助!

【问题讨论】:

  • 删除第二个function(result)中的then。您已经在那里使用箭头函数语法来声明函数。
  • 无论如何都要避免使用Promise constructor antipattern!顺便说一句,new Promise 回调中永远不需要try { … } catch(err) { reject(err) },构造函数会自动执行此操作。
  • 您的executeStep2 中的'[something]' 到底是什么,这实际上是一个可能引发异常的表达式吗?
  • 你能分享你的真实代码吗? Button.addEventListener('click', executeAction('0'));result => function(result) { 看起来都像错误
  • 如果这是节点,你为什么访问document

标签: javascript node.js promise


【解决方案1】:
executeStep1()
    .then(result => executeStep2(param1, result, input))
    .then(result => { // no function(result) here
       console.log('All done');
       resolve(result);
    })
    .catch(err => reject(err))
  ;

【讨论】:

  • 这更近了。当我运行它时它不再挂起。但是,我仍然收到UnhandledPromiseRejectionWarning 错误。
【解决方案2】:

当您调用使用承诺的函数时会产生错误:

myButton.addEventListener('click', executeAction('0'));

您还需要在此处捕获拒绝。

myButton.addEventListener('click', executeAction('0')
    .catch((error) => console.log('ERROR', error));

拒绝被捕获在函数内部,但不在外部范围内,因为executeAction('0') 返回一个承诺,或者它会但你将它用作非异步函数,所以它创建一个承诺然后返回一个待处理承诺不等待解决。这看起来是导致拒绝的原因,并且由于上述原因也没有处理。

这将解决它:

function executeAction(input) {      
  let param1 = 'A';
  return new Promise(function(resolve, reject) {
    try {
      executeStep1()
        .then(result => executeStep2(param1, result, input))
        .then(result => function(result) {
           console.log('All done');
           resolve(result);
        })
        .catch(err => reject(err))
      ;
    } catch (ex) {
      reject(ex);
    }
  });
}

您应该研究 async/await。它可以显着清理这段代码。

    async function getSomething() {
      try {
        // throw 'Test error detected.'
        return 'test'
      }
      catch (e) {
        throw e
      }
    }
    
    async function testing() {
      try {
        const sample = await getSomething()
        return sample
      } catch (e) {
        throw e
      }
    }
    
    testing()
      .then((data) => console.log(data))
      .catch((err) => console.log(err))

运行上面的示例,然后取消注释 throw。使用此模式获得最大的胜利。异常应该被抛出到函数被调用、显示、使用、渲染等的表面级别。函数应该简单地抛出错误。

这允许您使用错误处理中间件、高阶函数、侦听器、日志记录等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-16
    • 2019-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多