ZetCode

JS async/await

last modified June 16, 2022

JS async/await tutorial shows how to do asynchronous programming with async and await keywords.

JavaScript is an asynchronous programming language. It uses promises to handle asynchronous operations. Before introducing promises, asynchronous operations were hadled by callbacks.

A promise is a placeholder for an asynchronous task which is yet to be completed. (Promises are called futures in some programming languages.) The async and await keywords enable asynchronous, promise-based behavior to be written in a cleaner style.

With async keyword, we define an asynchronous function. Every async function returns a promise. Async functions can contain zero or more await expressions. The await keyword suspends execution of a function until the returned promise is fulfilled or rejected.

The await keyword is only valid inside async functions within regular JavaScript code.

Note: Async functions always return a promise. If the return value of an async function is not explicitly a promise, it is automatically wrapped in a promise.

JS async/await simple example

The following is a simple asynchronous JS code utilizing async/await keywords.

main.js
const work = () => {
    return new Promise(resolve => {
        setTimeout(() => resolve('doing work'), 3000);
    })
}

const doWork = async () => {
    console.log(await work());
}

console.log('before');
doWork();
console.log('after');

In the example, we have one asynchronous function.

const work = () => {
    return new Promise(resolve => {
        setTimeout(() => resolve('doing work'), 3000);
    })
}

The work function is a dummy function which represents a task lasting three seconds.

const doWork = async () => {
    console.log(await work());
}

The doWork is an async function which calls work. With await, it suspends execution until the work function is resolved.

doWork();

The doWork function is called.

$ node simple.js 
before
after
doing work

Note that the 'doing work' message is printed after console.log statements. So esentially, the doWork function does not block the statements in the main.js file.


Before async/await keywords were introduced, callbacks were used.

main.js
const work = () => {
    return new Promise(resolve => {
        setTimeout(() => resolve('doing work'), 3000);
    })
}

console.log('before');

work().then(e => {
    console.log(e);
    console.log('finished');
});

console.log('after');

This is the same example using a callback. It is more difficult to create more complex asynchronous code with callbacks.

JS async/await with fetch

The fetch is a global function which takes url and options parameters and returns a promise. The promise resolves to the response of the request.

let promise = fetch(url, [options])

If the options are not provided, a simple GET request downloading the contents of the url is generated.

<script>
    async function doRequest() {
        let url = 'http://webcode.me';
        let res = await fetch(url);

        if (res.ok) {

            let text = await res.text();

            return text;
        } else {
            return `HTTP error: ${res.status}`;
        }
    }

    doRequest().then(data => {
        console.log(data);
    });

</script>

An asynchronous GET request is generated with fetch in JS code in a browser.

JS async screenshot

In the next example, we create a screenshot of a webpage. We use the Puppeteer library.

$ npm i puppeteer

We install Puppeteer with npm i puppeteer command.

main.js
const puppeteer = require('puppeteer');

(async () => {

  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('http://webcode.me');
  await page.screenshot({ path: 'webcode.png' });

  await browser.close();
})();

Inside an anonymous function, we execute several asynchronous operations. Each of them is awaited with await.

In this article, we have created asynchronous JS programs with async and await keywords.

List all JavaScript tutorials.