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

时间:2014-07-30 18:28:22

标签: javascript promise es6-promise

我正在寻找一种方法,只有在另一个承诺失败时才能返回承诺

我该怎么做?

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

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,如果拒绝,则拒绝整个链
  4. 到目前为止,我已经完成了这项工作并且似乎有效。 (我正在使用when.js btw)

    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) }
    );
    

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

1 个答案:

答案 0 :(得分:6)

如下:

 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继续保留链。 promise构造函数几乎没用。
  • 您可以通过.then省略.then(null, function(){...中的第一个参数,但使用.catch更为简单,因为.then是别名。更一般地说,.catch会忽略不是函数的参数。
  • 拒绝和返回值传播,如果您不通过.then(或{{1}}的第二个参数)处理拒绝,它将直接移动到链中,直到您这样做。返回值也是如此 - 这就是为什么这里的前两行包含:
    • 尝试按用户名
    • 获取用户
    • 如果失败,请尝试通过电子邮件。

一般来说,您所描述的内容与同步代码中的异常的承诺和异常非常相似。学习如何有效地完成这类工作非常重要。