最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to break loop inside a promise? - Stack Overflow

programmeradmin2浏览0评论

I'm doing kind of QA (Question/Answers) application using the Bluebird library. So here's the scenario:

  1. User fill the form with answers for some number of questions (e.g 5 questions).
  2. A question has more than 1 possible answer: "Question has many answers"
  3. Answers are encrypted (bcrypt) on database using node.bcrypt
  4. When looping through answers, if user answer matches, there's no need to continue checking the answer for that question.

So it's a mon problem to solve when doing things synchronous, but I'm a little lost to do that async with promises.

Here's a sample of what I don't know how to proceed:

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

I'm doing kind of QA (Question/Answers) application using the Bluebird library. So here's the scenario:

  1. User fill the form with answers for some number of questions (e.g 5 questions).
  2. A question has more than 1 possible answer: "Question has many answers"
  3. Answers are encrypted (bcrypt) on database using node.bcrypt
  4. When looping through answers, if user answer matches, there's no need to continue checking the answer for that question.

So it's a mon problem to solve when doing things synchronous, but I'm a little lost to do that async with promises.

Here's a sample of what I don't know how to proceed:

  .then(function(answers) {
    var pare = Promise.promisify(bcrypt.pare);
    // foreach answer, I need to check like this
    // pare(answer.password, user.password).then(function(match){
    //      if (match) break; <-- something like this
    //   })
  })
Share Improve this question edited Mar 28, 2014 at 1:03 Benjamin Gruenbaum 277k89 gold badges521 silver badges517 bronze badges asked Feb 13, 2014 at 14:53 rizidororizidoro 13.4k18 gold badges60 silver badges86 bronze badges 3
  • You may have to get the encrypted answer separately before the loop, and inside the callback start the loop and just do basic checking (if hash == password) break; – tymeJV Commented Feb 13, 2014 at 14:59
  • @tymeJV I think I can't do that, cause when I hash the password with bcrypt, a different value is generated from the database previously generated value... that's the reason why I need the bcrypt pare function... Maybe I'm wrong... – rizidoro Commented Feb 13, 2014 at 15:06
  • Don't have my bcrypt repo up in front of me but that sounds right - callback hell :\ - this post might help: stackoverflow./questions/13214862/… – tymeJV Commented Feb 13, 2014 at 15:11
Add a ment  | 

3 Answers 3

Reset to default 3

Assuming you want to call the pares sequentially, this will do it:

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

It will "recursively" step trough the answers array, stopping on the first true result. To return the correct answer (instead of just true for "found") or null (if not found) like @Noseratio's code, you could use

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

or better the more verbose

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

The following solution (untested) implements a state machine to simulate foreach loop. The result promise is resolved when the match has been found, or when there is no more answers to pare:

  .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 (pare(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
  });

It could be a simple solution:

let breakLoop = false
for (let answer of arr) {
  if (breakLoop) continue
  pare(answer.password, user.password)
    .then(match => {
      if (match) breakLoop = true
    })
    .catch(err => breakLoop = true)
}
发布评论

评论列表(0)

  1. 暂无评论