View on GitHub

Matt's homepage

Bookmark this to keep an eye on new things I am learning.

Promises

Promises are used to wait for data, then act on it. Otherwise JS will just continue running your code as it is non-blocking.

Return Home

Standard non-blocking function

Without prompises and async / await, the following code will print:

End of long task
Complete end
End of timeout
function doALongTask() {
    // wait 1 seconds to simulate a slow operation
    setTimeout(() => {
            console.log("End of timeout");
        }, 1000);

    console.log("End of long task");
};

doALongTask();  
console.log('Complete end');

^ back to top ^

Async function with promise

The code will now print the following. complete end is non blocking, so prints immediately. end of long task and end of timeout are inside of an async function, which automatically returns a promise. This promise then uses the await keyword to wait for the timeout function to resolve, which it does after the timeout. The end long task then executes.

Complete end
End of timeout
End of long task
// async function with long op wrapped in a promise
async function doSomeLongTask() {
    await new Promise((resolve) => {  // waits for resolve before returning to other code
        // wait 2 seconds to simulate a slow operation
        setTimeout(() => {
            console.log("End of timeout");
            resolve(); // calls resolve
        }, 2000);
    });

    console.log("End of long task");
}

doSomeLongTask();  // waits for the long task function, then displays 1 and 2
console.log('Complete end'); // This is outside the function, so js runs this while the long 

^ back to top ^

Then-Catch

Promises can also return data (resolve-return), which can then be processed succinctly. If an error is encountered in the async function, it is caught later in the .catch() call.

// waits for resolve before returning value to caller
async function doThenLongTask() {
    let cntr = 5;
    await new Promise((resolve) => {  
        // wait 2 seconds to simulate a slow operation
        setTimeout(() => {
            cntr++
            resolve();
            //throw new Error("BLAH!!!!");
        }, 2000);
    });
    return cntr;
};


doThenLongTask()
    .then((data) => {
        return data + 4;
    })
    // subsequent data operations can be performed
    .then((data) => {
        console.log(data);
    })
    .catch(function (error) {
        console.log('Oops!', error);
    });

^ back to top ^

Async functions

Some functions are already aysnc, like fetch.

// do an async call to a jokes API, then wait to print the response.
fetch('https://icanhazdadjoke.com/', {
  headers: {
    "User-Agent": "node",
    "Accept": "application/json"
  }
})
  .then(res => res.json())
  .then(res => {
    console.log(res.joke)
  })
  .catch((error) => {
    console.log('ERROR:', error);
  });

^ back to top ^

Incompatibilities

For-each is not compatible with async. Everthing will run non-blocking in for-each. Use for-of instead. Eg:

const myArray = [1,2,3,4,5,6,7,8,9];

async function processArrayAsync(arr) {
    // arr.forEach(async (item) => { // does not support async operations
    for(const item of arr) {
        await someAsyncOperation(item);
        console.log(`Processed: ${item}`);
    };
}

function someAsyncOperation(item) {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve();
        },parseInt(item) * 500);
    });
}

processArrayAsync(myArray)
    .then(() => {
        console.log('All items processed');
    })
    .catch((error) => {
        console.log(`Error: ${error}`);
    });

Output

Processed: 1
Processed: 2
Processed: 3
Processed: 4
Processed: 5
Processed: 6
Processed: 7
Processed: 8
Processed: 9
All items processed

^ back to top ^

Parallel and wait for all

Wait for all async functions to complete before returning

async function processParallel() {
    const promise1 = Promise.resolve(3);
    const promise2 = 42;
    const promise3 = new Promise((resolve) => {
        setTimeout(resolve,4000, 'foo');
    });

    Promise.all([promise1,promise2,promise3])
        .then((values) => {
            console.log(values);
        });
}

processParallel();

^ back to top ^