Lessons in this course (11)

4. Asynchronous JavaScript in Node — callbacks, promises, async/await and the microtask queue

Intermediate★ Must knowLesson 4 of 11
js
// 1. Callbacks (error-first convention)
fs.readFile('a.txt', 'utf8', (err, text) => { if (err) return console.error(err); console.log(text); });

// 2. Promises
fs.promises.readFile('a.txt', 'utf8').then(console.log).catch(console.error);

// 3. async/await — cleanest
async function loadAll() {
  try {
    const [a, b] = await Promise.all([readFile('a.txt', 'utf8'), readFile('b.txt', 'utf8')]);   // in parallel
    return a + b;
  } catch (err) {
    console.error('load failed', err);
    throw err;
  }
}

// Execution order puzzle — a classic interview question
console.log('1 sync');
setTimeout(() => console.log('5 timeout'), 0);
setImmediate(() => console.log('6 immediate'));
Promise.resolve().then(() => console.log('4 promise microtask'));
process.nextTick(() => console.log('3 nextTick'));
console.log('2 sync');
// Output: 1, 2, 3, 4, then 5 and 6 (timeout vs immediate order can vary at top level; inside an I/O callback, immediate runs first)
APIRuns
process.nextTickRight after the current operation, before promises
Promise .then / await continuationMicrotask queue, after nextTick queue
setTimeout(fn, 0)Timers phase of the next loop iteration (≥ ~1 ms)
setImmediateCheck phase (after poll)

Unhandled promise rejections crash the process (default since Node 15) — always await or .catch, and add process.on('unhandledRejection', …) logging.