I'm doing kind of QA (Question/Answers) application using the Bluebird library. So here's the scenario:
So it's a common 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 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
// })
})
Breaking Out of For Loops. To break out of a for loop, you can use the endloop, continue, resume, or return statement. endfor; If condition is true, statementlist2 is not executed in that pass through the loop, and the entire loop is closed.
To pause the current promise, or to have it wait for the completion of another promise, simply return another promise from within then() .
Promise.all() will reject immediately upon any of the input promises rejecting. In comparison, the promise returned by Promise.allSettled() will wait for all input promises to complete, regardless of whether or not one rejects. Use allSettled() if you need the final result of every promise in the input iterable.
Assuming you want to call the compare
s sequentially, this will do it:
.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" 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) && compare((answer = answers[i++]).password, user.password).then(checkNext);
});
or better the more verbose
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);
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 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
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With