如何在承诺中打破循环?

riz*_*oro 7 javascript asynchronous node.js promise bluebird

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

  1. 用户填写表格并提供一些问题的答案(例如5个问题).
  2. 一个问题有多个可能的答案:"问题有很多答案"
  3. 使用node.bcrypt在数据库上对Answers进行加密(bcrypt)
  4. 循环回答时,如果用户回答匹配,则无需继续检查该问题的答案.

所以当做同步事情时,这是一个常见的问题需要解决,但我有点迷失与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
    //   })
  })
Run Code Online (Sandbox Code Playgroud)

Ber*_*rgi 3

假设您想按compare顺序调用 s,可以这样做:

.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);
    });
})
Run Code Online (Sandbox Code Playgroud)

它将“递归”地遍历数组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);
    });
Run Code Online (Sandbox Code Playgroud)

或者越详细越好

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);
Run Code Online (Sandbox Code Playgroud)