How to break a loop inside a promise?

I am making a QA application (question / answer) using the Bluebird library. So the script:

  • The user will fill out a form with answers to several questions (for example, 5 questions).
  • The question has more than one possible answer: "The question has many answers"
  • Responses are encrypted (bcrypt) in the database using node.bcrypt
  • When navigating through the answers, if the user answer matches, there is no need to continue checking the answer to this question.

So, this is a common problem to solve when doing something synchronously, but I lost a bit to do it asynchronously with promises.

Here is an example that I do not know how to proceed:

.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 // }) }) 
+7
javascript promise asynchronous bluebird
source share
3 answers

Assuming you want to call compare sequentially, this will do this:

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

It will "recursively" go through the answers array, stopping at the first true result. To return the correct answer (instead of true for "found") or null (if not found), for example, @Noseratio code, you can use

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

or better more detailed

 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); 
+3
source share

The following solution (untested) implements a state machine for modeling the foreach . The result promise is resolved when a match is found, or when there are no more answers to compare:

  .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 }); 
+1
source share

This might be a simple solution:

 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) } 
0
source share

All Articles