Skip to main content

Node JS

General aspects of Node JS, how it differs from browser JavaScript, and how it is used on the server side.

What is Node JS?​

Node.js is a JavaScript runtime environment built on Chrome's V8 engine. It lets you run JavaScript code on the server side, outside the browser. It was created by Ryan Dahl in 2009 with the goal of building highly scalable and efficient applications for handling I/O (input/output) operations.

For some reason, Node and its modules are now used on the server side...

Key features​

  • Asynchronous and non-blocking: Node uses asynchronous operations by default, which makes it ideal for applications that handle many simultaneous requests.
  • Single-threaded: Although it runs on a single thread, it can handle concurrency through the Event Loop and by delegating I/O operations to system threads through libuv.
  • Large ecosystem: It has npm, the largest ecosystem of open source packages.

Difference from JavaScript in the browser​

  • In the browser, JavaScript runs in the context of the DOM.
  • In Node.js, there is no DOM; you use modules such as fs or http to access the file system or create servers.

How can Node JS be concurrent?​

Node.js is single-threaded, but it can handle concurrency thanks to:

  • Event Loop: It manages asynchronous tasks and dispatches them.
  • libuv: A library that provides a thread pool that lets blocking tasks (such as disk or network access) run without blocking the main thread. These threads do not belong to Node; they belong to the operating system.

Example:

How can Node JS be concurrent
const fs = require('fs');

console.log('Inicio');

fs.readFile('archivo.txt', 'utf-8', (err, data) => {
if (err) throw err;
console.log('Contenido:', data);
});

console.log('Fin');

Event Loop​

The Event Loop is the mechanism that allows Node.js to run non-blocking operations, despite being single-threaded.

Event Loop phases (simplified):​

  1. Timers: Runs setTimeout and setInterval callbacks.
  2. Pending callbacks: Callbacks deferred by certain system operations.
  3. Idle/prepare: Internal to Node.
  4. Poll: Retrieves new events and runs I/O.
  5. Check: Runs setImmediate().
  6. Close callbacks: E.g. socket.on('close').
Event Loop Event Loop 1

Microtasks vs Macrotasks​

  • Microtasks: Promises (Promise.then), queueMicrotask.
  • Macrotasks: setTimeout, setInterval, setImmediate.

Example:

Microtasks vs Macrotasks
console.log('Inicio');

setTimeout(() => console.log('Timeout'), 0);

Promise.resolve().then(() => console.log('Promesa'));

console.log('Fin');

Expected output:

Inicio
Fin
Promesa
Timeout

What is a callback?​

A callback is a function that is passed as an argument to another function and is executed after that function finishes its work.

Callback example:

What is a callback
function saludar(nombre, callback) {
console.log(`Hola ${nombre}`);
callback();
}

saludar('Kevin', () => {
console.log('Callback ejecutado');
});

Callback Hell​

When many callbacks are nested, the code becomes unreadable. This is known as "callback hell".

Callback Hell
fs.readFile('archivo1.txt', 'utf-8', (err, data1) => {
if (err) throw err;
console.log('Archivo 1 leído');

fs.readFile('archivo2.txt', 'utf-8', (err, data2) => {
if (err) throw err;
console.log('Archivo 2 leído');

fs.readFile('archivo3.txt', 'utf-8', (err, data3) => {
if (err) throw err;
console.log('Archivo 3 leído');

fs.readFile('archivo4.txt', 'utf-8', (err, data4) => {
if (err) throw err;
console.log('Archivo 4 leído');
});
});
});
});

Promises​

A Promise represents a value that may be available now, in the future, or never.

States:

  • Pending: waiting.
  • Fulfilled: resolved successfully.
  • Rejected: failed.

Example:

Promises
const promesa = new Promise((resolve, reject) => {
setTimeout(() => resolve('Hecho!'), 1000);
});

promesa.then(res => console.log(res));

With async/await:

Promises (2)
async function saludar() {
const resultado = await promesa;
console.log(resultado);
}

saludar();

Difference between require/export and import/export​

Node.js has two module systems:

  • CommonJS: Uses require and module.exports.
  • ES6 Modules: Uses import and export.

This is because Node.js was created before ES6 modules were standardized.

Difference between require/export and
const fs = require('fs'); // CommonJS
Difference between require/export and (2)
import fs from 'fs'; // ES6 Modules

Node JS modules​

fs module​

It lets you work with the file system.

Example:

fs module
const fs = require('fs');

fs.readFile('archivo.txt', 'utf-8', (err, data) => {
if (err) throw err;
console.log(data);
});

http module​

It lets you create HTTP servers.

Example:

http module
const http = require('http');

const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hola desde Node.js');
});

server.listen(3000, () => console.log('Servidor en puerto 3000'));

path module​

It lets you work with file paths.

path module
const path = require('path');

const ruta = path.join(__dirname, 'archivo.txt');
console.log(ruta);

os module​

It provides information about the operating system.

os module
const os = require('os');

console.log('Sistema operativo:', os.platform());
console.log('Memoria libre:', os.freemem());
console.log('CPUs:', os.cpus());

process.nextTick() example​

process.nextTick() lets you run code asynchronously on the next iteration of the event loop, before any other asynchronous event:

process.nextTick() example
console.log('Inicio del programa');

// Runs immediately
console.log('1. Código síncrono');

// Runs on the next iteration of the event loop
process.nextTick(() => {
console.log('3. nextTick callback');
});

// Runs after nextTick
setTimeout(() => {
console.log('4. setTimeout callback');
}, 0);

console.log('2. Final del código síncrono');

// Output:
// Inicio del programa
// 1. Código síncrono
// 2. Final del código síncrono
// 3. nextTick callback
// 4. setTimeout callback

Common use case: Error handling​

Common use case: Error handling
function asyncFunction(callback) {
if (typeof callback !== 'function') {
// Use nextTick to handle errors asynchronously
process.nextTick(() => {
throw new TypeError('Callback debe ser una función');
});
return;
}

// Simulate an asynchronous operation
process.nextTick(callback);
}

// Usage
asyncFunction(() => {
console.log('Callback ejecutado correctamente');
});

Additional information or resources​


Self-Assessment Quiz​

Cargando cuestionario...