打破承诺链 - 停止执行下一个“then”

Posted

技术标签:

【中文标题】打破承诺链 - 停止执行下一个“then”【英文标题】:Break promise chain - stop the next 'then' from executing 【发布时间】:2018-03-18 13:08:59 【问题描述】:

我正在 Node/Express 中编写一个注册系统,并且我正在尝试使用 Promises。

问题是我在使用它们时收到一条错误消息:

错误:

(节点:64725)UnhandledPromiseRejectionWarning:未处理的承诺拒绝(拒绝 id:2):

有没有办法停在then

auth.isRegistered(email)
.then((registered) => 
    if ( !registered ) 
        req.flash('pleaseRegister', 'Looks like you haven\'t registered. Please register first.');
        req.session.user = user;
        res.redirect('/register')
    
)
.then(() => 
    return auth.isVerified(email);
)
.then((verified) => 
    if ( !verified ) 
        console.log('please verify');
        res.redirect('/register/verify');
     else 
        req.login(user, err => 
            if ( err ) return next(err);
            req.session.timestamp = Date.now();
            auth.updateLastLogin(email)
            .then(() => 
                res.redirect(req.session.returnTo || '/account');
            );
        );
    
);

【问题讨论】:

首先,您的错误似乎是一个警告。其次,您是否尝试过在您的承诺中添加catch 调用? if/else 就像你在最后一个 then 回调中所做的那样应该没问题,对 if (!registered) 做同样的事情。 哪个承诺被拒绝,有什么错误?您似乎从未catch您创建的任何承诺上出现任何错误,因此这似乎是意料之中的。 【参考方案1】:

您可以执行以下操作:

    当您想要中断承诺链时,引发自定义错误。 检查catch 回调,抛出的错误是自定义错误。如果是,就继续,否则用error对象调用next

例子:

let getBreackChainError = () => 
  let err = new Error();
  err.name = 'BreackChainError';
  return err;
;

auth
  .isRegistered(email)
  .then(registered => 
      if (!registered) 
        req.flash('pleaseRegister', 'Looks like you haven\'t registered. Please register first.');
        req.session.user = user;
        res.redirect('/register');
        throw getBreackChainError();
      
      return auth.isVerified(email);
  )
  .then(verified => 
      if (!verified) 
        console.log('please verify');
        res.redirect('/register/verify');
        throw getBreackChainError();
      
      return new Promise((resolve, reject) => 
        req.login(user, err => 
          if (err) 
            return reject(err);
          
          req.session.timestamp = Date.now();
          resolve();
        );
      );
  )
  .then(() => auth.updateLastLogin(email))
  .then(() => res.redirect(req.session.returnTo || '/account');
  .catch(err => 
    if (err.name !== 'BreackChainError') 
      next(err);
    
  );

注意。你不应该将回调与承诺混为一谈,使用其中之一。在上面的例子中,我promisified req.login,所以现在它返回了一个promise。

【讨论】:

反对者,请解释我的回答有什么问题? 我抛出“getBreackChainError”然后 node.js 退出脚本......我希望它停止承诺链而不是退出整个事情! 发现了问题 - 我使用的是 Promise.reject 而不是通过函数参数传递拒绝,如果有人能快速解释为什么我会欣赏它,如果不是生病创建我自己的线程。【参考方案2】:

语言:JavaScript

为简单起见,只需使用:- (以防您不想进一步处理错误)

throw new Error("An error occured");

示例:- (获取)

fetch("endpoint/resource", requestOptions)
        .then(response => 
            if(response != null && response.status == 404) 
                throw new Error("RECEIVED NULL OBJECT");
            
            return response;
        )
        .then(approvedResponse => approvedResponse.blob())
.catch(e => console.log(e));

【讨论】:

【参考方案3】:

UnhandledPromiseRejectionWarning:未处理的承诺拒绝(拒绝 id:2): 我相信这是因为您没有办法处理初始 .thens 中的错误,因此您会收到上述错误。它不是“停止”.then,而是正确处理错误。你可以做 (err)=> return 这基本上会“停止”它,但它会在你的应用程序中进行流量控制。

【讨论】:

以上是关于打破承诺链 - 停止执行下一个“then”的主要内容,如果未能解决你的问题,请参考以下文章

打破承诺链并根据链中被破坏(拒绝)的步骤调用函数

中途停止承诺链

Javascript - 链多个获取承诺

如何编写测试用例来覆盖承诺链中所有嵌套的“then”回调

具有可读函数名称的扁平化承诺链

完成后逃离承诺链[重复]