7

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

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

因此,在做同步的事情时解决这个问题是一个常见的问题,但是我有点迷失了用 Promise 做异步。

这是我不知道如何进行的示例:

  .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
    //   })
  })
4

3 回答 3

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

它将“递归地”遍历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);
于 2014-02-13T17:57:09.460 回答
1

以下解决方案(未经测试)实现了一个状态机来模拟foreach循环。result找到匹配项或没有更多答案可比较时,promise 将被解决:

  .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
  });
于 2014-02-13T20:05:34.943 回答
0

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

let breakLoop = false
for (let answer of arr) {
  if (breakLoop) continue
  compare(answer.password, user.password)
    .then(match => {
      if (match) breakLoop = true
    })
    .catch(err => breakLoop = true)
}
于 2019-01-18T14:21:41.613 回答