β Prerequsite
π₯ Grab the starter files for this section and open the project folder.
Download the Repo & Open starter Folder : 2-how-node-works
https://github.com/codevedadev/complete-node-bootcamp
If you already have it open, skip this step.
π Create File: events.js

π Custom Event
πΉ Step 1: Import the built-in events module
const EventEmitter = require('events');eventsis a built-in Node module β no npm install needed.By convention, the class is imported and named
EventEmitter(capitalized, since it's a class).
πΉ Step 2: Create an emitter instance
const myEmitter = new EventEmitter();βοΈ
myEmitteris now an object that can emit events and have listeners attached to it.

πΉ Step 3: Set up a listener for a custom event
myEmitter.on('newSale', () => {
console.log('There was a new sale!');
});π
.on(eventName, callback)β sets up a listener.π·οΈ
'newSale'is a made-up event name (could be anything βnewOrder,newCustomer, etc.).β³ The callback only runs once the event is actually emitted.
πΉ Step 4: Add a second listener for the same event
myEmitter.on('newSale', () => {
console.log('Customer name: Jonas');
});π₯ You can attach as many listeners as you want to the same event.
β Both will run when the event fires.
πΉ Step 5: Emit the event
myEmitter.emit('newSale');π€
.emit(eventName)triggers the event β like clicking a button.β οΈ Must come after the listeners are set up in the code, otherwise they won't catch it.

βΆοΈ Run it: node events.js
π₯οΈ Output:

π₯ Both listeners fire, in the order they were declared in the code.
π This is the Observer Pattern:
myEmitteris the subject/emitter; the two.on()listeners are the observers, watching and reacting.
πΉ Step 6: Pass data with the emitted event
Update the listener to accept an argument:
myEmitter.on('newSale', (stock) => {
console.log(`There are now ${stock} items left in stock.`);
});
Update the emit call to pass a value:
myEmitter.emit('newSale', 9);π₯οΈ Output:
There are now 9 items left in stock.
π¦ Any extra arguments passed to
.emit()get forwarded to the listener's callback as parameters.π Listeners for the same event fire synchronously, in declaration order β confirmed by seeing all three console logs print in sequence.
π‘ HTTP Server
πΉ Step 1: Add a second example lower in the same file β HTTP server events
Import the http module at the top of the file:

Create the server:

πΉ Step 2: Listen for the request event
server.on('request', (req, res) => {
console.log('Request received');
res.end('Request received');
});
π
serveris itself anEventEmitterinstance (inherited viahttp.ServerextendingEventEmitter).π
.on('request', ...)fires every time a request hits the server.π€
res.end(...)sends the response back to the client.
πΉ Step 3: Add a second listener for the same request event

π₯ Confirms you can attach multiple listeners to the same built-in event too, same as the custom
newSaleexample.
πΉ Step 4: Listen for the close event

π Fires when the server shuts down.
πΉ Step 5: Start the server

π
.listen(port, host, callback)β starts the server on port8000at127.0.0.1(localhost).β The callback is optional but useful for confirming startup.
π The process stays running (doesn't exit) because the event loop is still waiting for incoming I/O β this ties back to earlier event-loop concepts.
βΆοΈ Run it: node events.js
π₯οΈ Output:

πΉ Step 6: Test by making a request
π Open 127.0.0.1:8000 in the browser.

π₯οΈ Console output:

π Notice each listener fires twice.
πΉ Step 7: Investigate the duplicate logs
Add logging for the request URL:
server.on('request', (req, res) => {
console.log(req.url);
});
π₯οΈ Result: one log shows / and the other shows /favicon.ico.
π Browsers automatically send a separate request for
/favicon.ico(trying to fetch a tab icon) alongside your actual page request.π‘ That's why the
requestevent fires twice per page load β it's genuinely two separate requests, not a bug.

β Key Takeaway
π¨βπ» For custom events you create yourself (like
newSale), you must call.emit()yourself to trigger them.βοΈ For built-in Node modules (
http,fs, etc.), the module emits its own events internally whenever something relevant happens β you only need to attach.on()listeners to react, never.emit()them yourself.
const EventEmitter = require("events");
const http = require("http");
const myEmitter = new EventEmitter();
myEmitter.on("newSale", () => {
console.log("There was a new sale");
});
myEmitter.on("newSale", () => {
console.log("Customer name: Jonas");
});
myEmitter.on("newSale", (stock) => {
console.log(`There are now ${stock} items left in stock`);
});
myEmitter.emit("newSale", 9);
//////////////////
const server = http.createServer();
server.on("request", (req, res) => {
console.log("Request received!");
console.log(req.url);
res.end("Request received");
});
server.on("request", (req, res) => {
console.log("Another request π");
});
server.on("close", () => {
console.log("Server closed");
});
server.listen(8000, "127.0.0.1", () => {
console.log("Waiting for requests...");
});