Promises, rejections and returns in JavaScript
3 min read

Promises, rejections and returns in JavaScript

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 ifs and elses. 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 ifs and many console.logs. 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 ifs were evaluated.
Result of calling a promise with inner ifs and reject calls

Time for test number two. Can you make an empty return without any consequences?

Here goes the code again but this time with returns 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.

Result of calling a promise with inner ifs, reject calls and empty returns

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.

Screenshot-2022-03-09-at-20.28.52

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 rejection.

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.

Calling reject inside a promise multiple times

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?