如何在承诺中打破循环?

时间:2014-02-13 14:53:25

标签: javascript node.js asynchronous promise bluebird

我正在使用Bluebird库做一些QA(问题/答案)应用程序。所以这是场景:

  1. 用户填写表格并提供一些问题的答案(例如5个问题)。
  2. 一个问题有多个可能的答案:“问题有很多答案”
  3. 使用node.bcrypt
  4. 在数据库上对答案进行加密(bcrypt)
  5. 在循环回答时,如果用户回答匹配,则无需继续检查该问题的答案。
  6. 所以当做同步事情时,这是一个常见的问题需要解决,但我有点迷失与promises异步。

    以下是我不知道如何处理的示例:

      .then(function(answers) {
        var compare = Promise.promisify(bcrypt.compare);
        // foreach answer, I need to check like this
        // compare(answer.password, user.password).then(function(match){
        //      if (match) break; <-- something like this
        //   })
      })
    

3 个答案:

答案 0 :(得分:3)

假设你想按顺序调用compare,这样就可以了:

.then(function(answers) {
    var compare = Promise.promisify(bcrypt.compare),
        i = 0;
    return Q(false).then(function checkNext(res) {
        return res ||
               i<answers.length && compare(answers[i++].password, user.password)
                                     .then(checkNext);
    });
})

它会“递归地”进入answers数组,停在第一个true结果上。要返回正确的答案(而不只是true代表“找到”)或null(如果没有找到),如@ Noseratio代码,您可以使用

    var i = 0, answer;
    return Q(false).then(function checkNext(res) {
        return res ? answer : (i<answers.length || null) && compare((answer = answers[i++]).password, user.password).then(checkNext);
    });

或更好的更详细

function next(i) {
    if (i < answers.length)
        return compare(answers[i].password, user.password).then(function(res) {
             return res ? answers[i] : next(i+1);
        });
    else
        return null;
}
return next(0);

答案 1 :(得分:1)

以下解决方案(未经测试)实现状态机以模拟foreach循环。找到匹配项后,或者没有更多答案可供比较时,result承诺会得到解决:

  .then(function(answers) {
    var result = new Promise();
    var i = 0;
    function nextStep() {
      if (i >= answer.length)
        result.resolve(null);
      else {
        var answer = answers[i];
        if (compare(answer.password, user.password).then(function(match) {
          if (match)
            result.resolve(answer);
          else {
            i++;
            nextStep(); // do the next step
          }
        })
      }
    }
    process.nextTick(nextStep); // do the first step asynchronously    
    return result; // return the result as a promise
  });

答案 2 :(得分:0)

这可能是一个简单的解决方案:

        Authenticator.setDefault(new Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(user, pass.toCharArray());
            }
        });
相关问题