# Promises

Promises are a way in Javascript to handle asynchronous code.

Before getting started on promises, we first need to know what synchronous and asynchronous code is.

# Synchronous vs. asynchronous

Take a look at the following code example:

See the Pen FSSynch by Jitse Beyens (@BeyensJ) on CodePen.

Every line of this code is executed after the previous has finished. This is called synchronous code. It is how most of JavaScript code is executed and behaves exactly as you would expect.

But not all code works like this. Take a look at the next example:

See the Pen FSAsync by Jitse Beyens (@BeyensJ) on CodePen.

In step 1 and 2, we called a setTimeout() function with a 2 and 1 second delay. The code in these functions doesn't execute immediately after the previous line, but only after their timers are up. The next lines of code also don't wait for these functions to finish. Once the timers are done the code in the setTimeout() functions gets executed, regardless of what other code already ran after it.

This method of running code is called asynchronous (async) code. You execute a function that will eventually do something, but while you are waiting for that to finish, you let your other code go on.

# Promise objects

The promise object is a way in Javascript to organise and keep track of your async functions.

Just as the word says, a promise is an object that will eventually do something.

You can make a new promise object with new Promise(), and once it is made, it has 3 states:

  • pending: it has no response yet, code is not yet finished, please wait.
  • fullfilled: response is ready, code has finished executing, done.
  • rejected: an error occurred and there is no data.

Most of the time, your promise will give you a return value that you want to use in your program, so you will need a way to run some code after the promise is done.

You can do this by putting .then(data => ...) after the call to your promise. The code block you put there will be executed if your promise is fullfilled.

If your promise is not fulfilled and encountered an error however, you can also add .catch(error => ...). This will run in case your promise has been rejected.

To make use of all that, you can create and run a promise like this:

const promise = new Promise((resolve, reject) => {
    // do something that gives some data back after a certain time
    if (/* everything turned out fine -> resolve the data */) {
        resolve(data);
    } else {
        reject(new Error('Oops, something went wrong'));
    }
});

promise // without parentheses!
    .then(data => console.log(data)) // the data from the 'resolved' promise is available and can be used now
    .catch(error => console.error(error));
1
2
3
4
5
6
7
8
9
10
11
12

Or if you want to include parameters in your promise, like this:

const promise = (param1, param2) => {
    return new Promise((resolve, reject) => {
        // do something that gives some data back after a certain time
        if (/* everything turned out fine -> resolve the data */) {
            resolve(data);
        } else {
            reject(new Error('Oops, something went wrong'));
        }
    });
}

promise(param1, param2) // with parentheses of course
    .then(() => console.log('resolved')) // the data from the 'resolved' promise is available
    .catch(error => console.error(error));
1
2
3
4
5
6
7
8
9
10
11
12
13
14

Now how would a setTimeout() function look if you would wrap it in a promise to control it's outcome better? Lets take a look:

# Async function rewritten with Promises

If we now make use of this newly created Promise object, we can recreate the asynchronous function from above, but make it sequential as well as async. This means that the parts of the function will be run in sequence, but while the function is running, other code will still be able to run.

See the Pen FSAsync by Jitse Beyens (@BeyensJ) on CodePen.

Last Updated: 5/2/2024, 4:48:28 PM