如何获得在承诺链中成功的第一个承诺的价值

How to get the value of the first promise that succeeds in a chain of promises

本文关键字:一个承诺 成功 何获得 承诺      更新时间:2023-09-26

我正在寻找一种仅在另一个承诺失败时才返回承诺的方法。

我该怎么做?

我的承诺看起来像这样(当然我已经删除了不相关的代码(:

getUserByUsername = function(username) {
    return promise(function(resolve, reject) {
       user = userModel.getByUsername(username);
       if ( user ) { resolve(user); } else { reject("user not found"); }
    });
};
getUserByEmail = function(email) {
    return promise(function(resolve, reject) {
       user = userModel.getByEmail(email);
       if ( user ) { resolve(user); } else { reject("user not found"); }
    });
};
checkPassword = function(user, password) {
    return promise(function(resolve, reject) {
       if ( user.isValidPassword(password) ) { resolve() } else { reject("password mismatch"); }
    });
};

我想按以下顺序组合它们

  1. 呼叫getUserByUsername,如果拒绝,则呼叫getUserByEmail
  2. 返回从上述两个承诺中解析的人的值,或者如果两个承诺都失败,则拒绝整个链。
  3. 使用值调用checkPassword,如果它拒绝,则拒绝整个链

到目前为止,我已经这样做了,它似乎有效。(我正在使用什么时候.js顺便说一句(

getUserByUsername(usernameOrEmail)
.then( 
    function(user) { return user; }, 
    function() { return getUserByEmail(usernameOrEmail) } 
)
.then( function(user) { return checkPassword(user, password) } )
.done( 
    function() { console.log('success'); }, 
    function(err) { console.log('failure', err) }
);

所以这段代码有效,但我很确定应该有更优雅的方式来做到这一点(我认为我的代码看起来更像是一个黑客(。

像这样的事情呢:

 getUserByUsername(usernameOrEmail).
 catch(getUserByEmail.bind(null, usernameOrEmail)).
 then(function(user){
     if(!isValidPassword(user, password)) throw new Error("Invalid Password");
 }).then(function(){
     // success
 }, function(){
    //fail
 });

关键事项:

  • 您可以throw拒绝承诺,return继续链条。承诺构造函数几乎没有用处。
  • 您可以通过执行.then(null, function(){...来省略.then中的第一个参数,但是使用.catch是该参数的别名更简单。更一般地说,.then忽略不是函数的参数。
  • 拒绝
  • 和返回值传播,如果你不通过.catch(或.then的第二个参数(处理拒绝,它将简单地跨链移动,直到你这样做。返回值也是如此 - 这就是为什么这里的前两行包含:
    • 尝试通过用户名获取用户
    • 如果失败,请尝试通过电子邮件。

一般来说,你所描述的内容在同步代码中与承诺和异常相似是非常常见的。学习如何有效地做这种事情很重要。