Back to Backend & APIs

Module 1: Node.js Fundamentals

Master Node.js core concepts, event loop, and asynchronous programming patterns.

What is Node.js?

Node.js is JavaScript running on the server. Think of it as taking the JavaScript engine from Chrome (V8) and using it to build backend applications. It's fast, scalable, and perfect for I/O-heavy applications like APIs, real-time apps, and microservices.

🚀 Why Node.js?

  • JavaScript Everywhere: Same language for frontend and backend
  • Non-Blocking I/O: Handle thousands of connections efficiently
  • NPM Ecosystem: 2+ million packages available
  • Fast Execution: V8 engine compiles JS to machine code
  • Active Community: Huge ecosystem and support
  • Real-time Ready: Perfect for WebSockets and streaming

The Event Loop

The event loop is Node.js's secret weapon. It's like a restaurant manager who takes orders (requests), delegates cooking to the kitchen (async operations), and serves food when ready - all without blocking other customers.

How the Event Loop Works:

// Synchronous (blocking)

console.log('Start');

const result = heavyComputation(); // Blocks everything

console.log('End');

// Asynchronous (non-blocking)

console.log('Start');

setTimeout(() => {

console.log('Async operation');

}, 1000); // Doesn't block

console.log('End'); // Runs immediately

// Output:

// Start

// End

// Async operation (after 1 second)

Event Loop Phases:

  • • Timers: Execute setTimeout/setInterval callbacks
  • • Pending Callbacks: I/O callbacks deferred to next loop
  • • Poll: Retrieve new I/O events
  • • Check: Execute setImmediate callbacks
  • • Close: Close callbacks (socket.on('close'))

Modules & NPM

CommonJS Modules:

// math.js - Export functions

function add(a, b) {

return a + b;

}

function multiply(a, b) {

return a * b;

}

module.exports = { add, multiply };

// app.js - Import functions

const { add, multiply } = require('./math');

console.log(add(2, 3)); // 5

console.log(multiply(4, 5)); // 20

// ES Modules (modern)

// math.mjs

export function add(a, b) {

return a + b;

}

// app.mjs

import { add } from './math.mjs';

NPM Basics:

# Initialize project

npm init -y

# Install packages

npm install express

npm install --save-dev nodemon

# Install globally

npm install -g typescript

# Update packages

npm update

# Remove package

npm uninstall express

Async Programming

1. Callbacks (Old Way)

const fs = require('fs');

fs.readFile('file.txt', 'utf8', (err, data) => {

if (err) {

console.error(err);

return;

}

console.log(data);

});

// Callback hell (avoid this!)

getData((data1) => {

processData(data1, (data2) => {

saveData(data2, (result) => {

console.log(result);

});

});

});

2. Promises (Better)

const fs = require('fs').promises;

fs.readFile('file.txt', 'utf8')

.then(data => {

console.log(data);

return processData(data);

} )

.then(result => console.log(result))

.catch(err => console.error(err));

// Creating promises

function delay(ms) {

return new Promise(resolve => {

setTimeout(resolve, ms);

});

}

delay(1000).then(() => console.log('Done!'));

3. Async/Await (Best)

const fs = require('fs').promises;

async function readAndProcess() {

try {

const data = await fs.readFile('file.txt', 'utf8');

const processed = await processData(data);

const result = await saveData(processed);

console.log(result);

} catch (err) {

console.error(err);

}

}

readAndProcess();

// Parallel execution

const [user, posts, comments] = await Promise.all([

fetchUser(),

fetchPosts(),

fetchComments()

]);

File System & Streams

File Operations:

const fs = require('fs').promises;

const path = require('path');

// Read file

const content = await fs.readFile('data.txt', 'utf8');

// Write file

await fs.writeFile('output.txt', 'Hello World');

// Append to file

await fs.appendFile('log.txt', 'New log entry\n');

// Check if file exists

try {

await fs.access('file.txt');

console.log('File exists');

} catch {

console.log('File does not exist');

}

// List directory

const files = await fs.readdir('./uploads');

// Create directory

await fs.mkdir('./new-folder', { recursive: true });

// Delete file

await fs.unlink('temp.txt');

// Path operations

const fullPath = path.join(__dirname, 'uploads', 'file.txt');

const ext = path.extname('file.txt'); // '.txt'

const basename = path.basename('/path/to/file.txt'); // 'file.txt'

Streams (Efficient for Large Files):

const fs = require('fs');

// Read stream (memory efficient)

const readStream = fs.createReadStream('large-file.txt');

readStream.on('data', (chunk) => {

console.log('Received chunk:', chunk.length);

});

readStream.on('end', () => {

console.log('Finished reading');

});

// Write stream

const writeStream = fs.createWriteStream('output.txt');

writeStream.write('Hello ');

writeStream.write('World');

writeStream.end();

// Pipe (copy file efficiently)

const source = fs.createReadStream('input.txt');

const dest = fs.createWriteStream('output.txt');

source.pipe(dest);

Built-in HTTP Server

const http = require('http');

const server = http.createServer((req, res) => {

// Set response headers

res.setHeader('Content-Type', 'application/json');

// Route handling

if (req.url =>= '/api/users' && req.method =>= 'GET') {

res.statusCode = 200;

res.end(JSON.stringify({ users: ['Alice', 'Bob'] }));

} else if (req.url =>= '/api/users' && req.method =>= 'POST') {

let body = '';

req.on('data', chunk => {

body += chunk.toString();

});

req.on('end', () => {

const user = JSON.parse(body);

res.statusCode = 201;

res.end(JSON.stringify({ message: 'User created', user }));

});

} else {

res.statusCode = 404;

res.end(JSON.stringify({ error: 'Not found' }));

}

});

const PORT = 3000;

server.listen(PORT, () => {

console.log(`Server running on port ${PORT} `);

});

Environment Variables

# .env file

PORT>3000

DATABASE_URL>mongodb://localhost:27017/mydb

JWT_SECRET>your-secret-key

NODE_ENV>development

// app.js

require('dotenv').config();

const port = process.env.PORT || 3000;

const dbUrl = process.env.DATABASE_URL;

const isProduction = process.env.NODE_ENV =>= 'production';

console.log('Port:', port);

console.log('Environment:', process.env.NODE_ENV);

📚 Module Summary

You've mastered Node.js fundamentals:

  • ✓ Event loop and non-blocking I/O
  • ✓ CommonJS and ES modules
  • ✓ NPM package management
  • ✓ Async programming (callbacks, promises, async/await)
  • ✓ File system operations and streams
  • ✓ Built-in HTTP server
  • ✓ Environment variables

Next: Learn Express.js framework for building APIs!