Promises, rejections and returns in JavaScript
How do you exit a JavaScript promise? Does calling reject()
automatically exit the code?
These were the questions bothering me as I was trying to refactor a lengthy and intricate Promise, with lots of inner if
s and else
s. For better readability and an easier to understand structure, my plan was to use consecutive if
checks that would reject
if certain conditions were met and skip any subsequent evaluations.
Only one doubt was stressing me: was it enough to simply call reject()
to stop the code execution? Sure, I could have read the documentation but why not make a test? Practice usually beats theory... in theory.
My test as simple as they come. One Promise, many if
s and many console.log
s. Instead of following the money, I planned to follow the logs.
var test = function () {
return new Promise(function (resolve, reject) {
let my_var = 5;
if (my_var > 4) {
console.log('More than 4');
reject();
}
if (my_var > 3) {
console.log('More than 3');
reject();
}
if (my_var > 2) {
console.log('More than 2');
reject();
}
if (my_var > 1) {
console.log('More than 1');
reject();
}
console.log('resolving!');
resolve();
});
}
And what was the result? You can see it in the screenshot below.
Calling reject
did not stop the execution and all the if
s were evaluated.
Time for test number two. Can you make an empty return
without any consequences?
Here goes the code again but this time with return
s sprinkled inside the if
evaluations.
var test = function () {
return new Promise(function (resolve, reject) {
let my_var = 5;
if (my_var > 4) {
console.log('More than 4');
reject();
return;
}
if (my_var > 3) {
console.log('More than 3');
reject();
return;
}
if (my_var > 2) {
console.log('More than 2');
reject();
return;
}
if (my_var > 1) {
console.log('More than 1');
reject();
return;
}
console.log('resolving!');
resolve();
});
}
This time, everything worked properly, as seen below.
The first return
call exited the promise and no other evaluations were made.
The promise itself also worked properly. My test
variable returned a proper promise, with a functional then
and catch
block.
test()
.then(function () {
console.log('resolved');
})
.catch(function () {
console.log('rejected');
});
See? All good.
With my original question answered (yes, you can exit a promise with a return
call), I turned to a new quest. In the first version of the code, where reject
was called multiple times, which statement was the returned one?
Keeping that in mind, I altered the code and added a specific value to each reject
ion.
var test = function () {
return new Promise(function (resolve, reject) {
let my_var = 5;
if (my_var > 4) {
console.log('More than 4');
reject(4);
}
if (my_var > 3) {
console.log('More than 3');
reject(3);
}
if (my_var > 2) {
console.log('More than 2');
reject(2);
}
if (my_var > 1) {
console.log('More than 1');
reject(1);
}
console.log('resolving!');
resolve();
});
}
test()
.then(function () {
console.log('resolved');
})
.catch(function (err) {
console.log('rejected with code', err);
});
Can you guess the answer?
It was the first one. As seen in the screenshot below, even though each if
statement was evaluated and reject
was called multiple times, only the first reject
had an impact.
And there you have it.
Could I have read the documentation to find these simple answers? Sure but then why deprive myself of a fun and quick test?