Node.js Fundamentals

In this section, we’ll explore the core concepts of Node.js, including modules, the module system, event-driven architecture, and asynchronous programming. Understanding these fundamentals is crucial for building efficient and scalable applications with Node.js.

Understanding Modules and the Module System

Node.js uses a modular system that allows you to organize your code into manageable, reusable pieces. Each piece of code is called a module.

  1. Creating and Exporting a Module: Create a file named math.js:

    javascript
    	// math.js
    	// This module provides basic arithmetic functions
    	
    	// Function to add two numbers
    	function add(a, b) {
    	  return a + b;
    	}
    	
    	// Function to subtract two numbers
    	function subtract(a, b) {
    	  return a - b;
    	}
    	
    	// Exporting the functions to be used in other files
    	module.exports = {
    	  add,
    	  subtract
    	};
  2. Importing and Using a Module: Create another file named app.js:

    javascript
    	// app.js
    	// Importing the 'math' module
    	const math = require('./math');
    	
    	// Using the functions from the 'math' module
    	const sum = math.add(5, 3);
    	const difference = math.subtract(9, 4);
    	
    	// Logging the results to the console
    	console.log(`Sum: ${sum}`); // Output: Sum: 8
    	console.log(`Difference: ${difference}`); // Output: Difference: 5

    Run the script:

    bash
    	node app.js

Using Built-in Modules

Node.js comes with several built-in modules that provide various functionalities. One of the most commonly used modules is fs (file system).

Example: Reading a file using the fs module:

Create a file named example.txt with some content.

Replace your index.js file with the following code:

javascript
	// Importing the 'fs' module
	const fs = require('fs');
	
	// Reading the content of a file asynchronously
	fs.readFile('example.txt', 'utf8', (err, data) => {
	  if (err) {
	    console.error('Error reading file:', err);
	    return;
	  }
	  // Logging the content of the file to the console
	  console.log(data);
	});

Event-Driven Architecture

Node.js is designed around an event-driven architecture, which makes it efficient and scalable. The events module is used to handle events in Node.js.

Example: Creating and using an event emitter:

javascript
	// Importing the 'events' module
	const EventEmitter = require('events');
	
	// Creating an instance of EventEmitter
	const myEmitter = new EventEmitter();
	
	// Defining an event handler
	myEmitter.on('greet', () => {
	  console.log('Hello, world!');
	});
	
	// Emitting the 'greet' event
	myEmitter.emit('greet');

Asynchronous Programming and Promises

Node.js is built for asynchronous programming. Understanding how to work with callbacks, Promises, and async/await is essential.

  1. Using Callbacks:

    javascript
    	// Asynchronous function using a callback
    	function fetchData(callback) {
    	  setTimeout(() => {
    	    const data = { id: 1, name: 'John Doe' };
    	    callback(null, data);
    	  }, 2000);
    	}
    	
    	// Calling the function and handling the callback
    	fetchData((err, data) => {
    	  if (err) {
    	    console.error('Error fetching data:', err);
    	    return;
    	  }
    	  console.log('Data:', data);
    	});
  2. Using Promises:

    javascript
    	// Function that returns a Promise
    	function fetchData() {
    	  return new Promise((resolve, reject) => {
    	    setTimeout(() => {
    	      const data = { id: 1, name: 'John Doe' };
    	      resolve(data);
    	    }, 2000);
    	  });
    	}
    	
    	// Calling the function and handling the Promise
    	fetchData()
    	  .then((data) => {
    	    console.log('Data:', data);
    	  })
    	  .catch((err) => {
    	    console.error('Error fetching data:', err);
    	  });
  3. Using Async/Await:

    javascript
    	// Function that returns a Promise
    	function fetchData() {
    	  return new Promise((resolve, reject) => {
    	    setTimeout(() => {
    	      const data = { id: 1, name: 'John Doe' };
    	      resolve(data);
    	    }, 2000);
    	  });
    	}
    	
    	// Async function that uses await
    	async function getData() {
    	  try {
    	    const data = await fetchData();
    	    console.log('Data:', data);
    	  } catch (err) {
    	    console.error('Error fetching data:', err);
    	  }
    	}
    	
    	// Calling the async function
    	getData();