Event Emitters
Part of the Node.js Basics section of Coddy's Node.js journey. Lesson 29 of 33.
The store should announce that a note was added without knowing who wants to hear it.
An EventEmitter from node:events keeps a list of listeners for each event name. on(name, fn) adds a listener; emit(name, ...args) calls every listener for that name, straight away, with those arguments. A listener added after the emit hears nothing.
import { EventEmitter } from 'node:events';
const door = new EventEmitter();
door.on('open', (who) => console.log(`${who} came in`));
door.on('open', () => console.log('Ding!'));
door.emit('open', 'Ada');
// Ada came in, then Ding!new EventEmitter() creates an emitter, an object that has on and emit. To give an existing object those methods, copy its properties onto a new emitter: Object.assign(new EventEmitter(), { notes: [] }) returns an emitter that also has notes.
Challenge
EasyThis step opens the course’s prepared notes command-line tool project, rather than your project files from Timers (including notes.js). Your earlier work stays in its own lesson. Read the supplied files before editing store.js. This copy contains the notes commands and asynchronous file helpers.
The store should announce each new note, and let other code decide what to do about it. Turn the store into an event emitter.
- In
store.js, makestoreanEventEmitterthat keeps all its own properties and methods. ImportEventEmitterfromnode:events.new EventEmitter()creates a new, empty emitter. Copy the store's object onto that emitter withObject.assign, as the lesson shows. - In
store.js, inadd, after the notes are saved, emit anaddedevent with two values: the note's text and its number. - In
notes.js, listen foraddedon the store. The listener printsSaved note, the number, and a full stop. Attach it near the top, before the commands run, so it is already listening whenaddemits. Theaddbranch itself prints nothing now; it only callsstore.add.
node notes.js add Buy bread prints one line with the new note's number, such as:
Saved note 3.After clear, add Buy milk prints Saved note 1., and add Call Ada prints Saved note 2..
Try it: type add Buy bread in the box after $ node notes.js and press Enter. You see Saved note and the new number, printed by your listener. Then type clear, add Buy milk and add Call Ada: you see Saved note 1., then Saved note 2..
Try it yourself
import { existsSync } from 'node:fs';
import { readFile, writeFile } from 'node:fs/promises';
const file = 'notes.json';
const readJson = async (name, fallback) => {
if (!existsSync(name)) {
return fallback;
}
try {
return JSON.parse(await readFile(name, 'utf8'));
} catch (err) {
console.error(`${name} is damaged: ${err.message}`);
process.exit(1);
}
};
const [notes, settings] = await Promise.all([readJson(file, []), readJson('settings.json', {})]);
const store = {
notes,
settings,
async save() {
await writeFile(file, JSON.stringify(this.notes, null, 2));
},
async add(text) {
this.notes.push(text);
await this.save();
return this.notes.length;
},
async remove(n) {
const [text] = this.notes.splice(n - 1, 1);
await this.save();
return text;
},
};
export default store;
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