Menu
CoddyTech

Async and Await

Part of the Node.js Basics section of Coddy's Node.js journey. Lesson 23 of 33.

A chain of .then calls reads differently from how you think about the steps: read, then parse, then save.

Inside an async function, await pauses until a promise settles and gives you its value. A failed promise throws there, so try and catch handle it. In a module, await also works at the top level.

import { readFile } from 'node:fs/promises';

const loadConfig = async () => {
    try {
        return JSON.parse(await readFile('config.json', 'utf8'));
    } catch {
        return {};
    }
};

const config = await loadConfig();
console.log(config.port ?? 3000);

An async function always returns a promise, so its caller awaits it too. Forget an await and you get the promise itself, Promise { <pending> }, instead of its value.

challenge icon

Challenge

Easy

This step opens the course’s prepared notes command-line tool project, rather than your project files from Promises (including count.js). Your earlier work stays in its own lesson. Read the supplied files before editing store.js. This copy contains the promise-based notes reader and its error handling.

store.js now uses the promise versions of readFile and writeFile, and its methods are async. But nothing waits for the promises yet, so every command breaks. Add await wherever a promise must finish before the next step.

  1. In store.js, in load, wait for readFile before JSON.parse uses the text.
  2. In store.js, load is async, so it returns a promise. Wait for it where the store sets notes. A module may use await at the top level, outside any function.
  3. In store.js, wait for writeFile in save, and wait for this.save() in add and in remove.
  4. In notes.js, store.add and store.remove are async now. Wait for them in the add and done branches, so n and removed hold values, not promises.

That makes seven awaits in all. Every command then works as before. list shows the notes in notes.json. With the two starting notes, add Buy bread prints Saved note 3., and done 1 then prints Done: Buy milk.

Try it: type list in the box after $ node notes.js before you change anything. You see notes.json is damaged: ..., but the file is fine: JSON.parse was given a promise instead of the file's text. After your changes, list shows the notes again. Then type add Buy bread and see Saved note 3.. Type done 1 and see Done: Buy milk.

Try it yourself

import { existsSync } from 'node:fs';
import { readFile, writeFile } from 'node:fs/promises';

const file = 'notes.json';

// readFile and writeFile now return promises. Wait for each with await.
const load = async () => {
    if (!existsSync(file)) {
        return [];
    }
    try {
        return JSON.parse(readFile(file, 'utf8'));
    } catch (err) {
        console.error(`notes.json is damaged: ${err.message}`);
        process.exit(1);
    }
};

const store = {
    notes: load(),
    async save() {
        writeFile(file, JSON.stringify(this.notes, null, 2));
    },
    async add(text) {
        this.notes.push(text);
        this.save();
        return this.notes.length;
    },
    async remove(n) {
        const [text] = this.notes.splice(n - 1, 1);
        this.save();
        return text;
    },
};

export default store;
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Node.js Basics

Practice on your own: Express playground