BAB 2: Node.js Fundamental

BAB 2: Node.js Fundamental

2.1 Pengenalan Node.js

2.1.1 Apa itu Node.js?

Node.js adalah runtime environment JavaScript yang dibangun di atas V8 JavaScript engine Chrome. Node.js memungkinkan pengembang untuk menjalankan JavaScript di sisi server.

2.1.2 Fitur Utama Node.js

  1. Single-threaded dengan event loop

  2. Non-blocking I/O

  3. Event-driven programming

  4. Cross-platform

  5. Extensive package ecosystem (NPM)

2.1.3 Arsitektur Node.js

Application (JavaScript)

   Node.js

 V8 Engine + libuv

Operating System

2.2 NPM (Node Package Manager)

2.2.1 Pengenalan NPM

NPM adalah package manager standar untuk Node.js yang memungkinkan developer untuk:

  • Menginstal package/module

  • Mengelola dependencies

  • Menjalankan script

  • Membagikan code

2.2.2 Package.json

{
  "name": "my-app",
  "version": "1.0.0",
  "description": "My Node.js application",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js",
    "test": "jest"
  },
  "dependencies": {
    "express": "^4.18.2",
    "mysql2": "^3.6.0"
  },
  "devDependencies": {
    "nodemon": "^3.0.1",
    "jest": "^29.6.0"
  }
}

2.2.3 NPM Commands

# Inisialisasi project baru
npm init

# Inisialisasi dengan default values
npm init -y

# Install package
npm install express

# Install development dependency
npm install --save-dev nodemon

# Install package global
npm install -g nodemon

# Uninstall package
npm uninstall express

# Update packages
npm update

# List installed packages
npm list

2.2.4 Semantic Versioning

Format: MAJOR.MINOR.PATCH

  • Major: Perubahan yang tidak backward compatible

  • Minor: Penambahan fitur yang backward compatible

  • Patch: Bug fixes yang backward compatible

Contoh:

{
  "dependencies": {
    "express": "^4.18.2",  // ^ = update minor dan patch
    "mysql2": "~3.6.0",    // ~ = update patch saja
    "moment": "2.29.4"     // exact version
  }
}

2.3 Asynchronous Programming

2.3.1 Callbacks

// Contoh callback
const fs = require('fs');

fs.readFile('file.txt', 'utf8', (err, data) => {
  if (err) {
    console.error('Error:', err);
    return;
  }
  console.log('Data:', data);
});

// Callback Hell (Anti-pattern)
fs.readFile('file1.txt', 'utf8', (err, data1) => {
  if (err) return console.error(err);
  fs.readFile('file2.txt', 'utf8', (err, data2) => {
    if (err) return console.error(err);
    fs.readFile('file3.txt', 'utf8', (err, data3) => {
      if (err) return console.error(err);
      console.log(data1, data2, data3);
    });
  });
});

2.3.2 Promises

// Membuat Promise
const myPromise = new Promise((resolve, reject) => {
  const success = true;
  if (success) {
    resolve('Operation successful');
  } else {
    reject(new Error('Operation failed'));
  }
});

// Menggunakan Promise
myPromise
  .then(result => console.log(result))
  .catch(error => console.error(error));

// Promise chaining
const fs = require('fs').promises;

fs.readFile('file1.txt', 'utf8')
  .then(data1 => {
    console.log(data1);
    return fs.readFile('file2.txt', 'utf8');
  })
  .then(data2 => {
    console.log(data2);
    return fs.readFile('file3.txt', 'utf8');
  })
  .then(data3 => {
    console.log(data3);
  })
  .catch(error => {
    console.error('Error:', error);
  });

2.3.3 Async/Await

// Async function
async function readFiles() {
  try {
    const data1 = await fs.readFile('file1.txt', 'utf8');
    const data2 = await fs.readFile('file2.txt', 'utf8');
    const data3 = await fs.readFile('file3.txt', 'utf8');
    
    console.log(data1, data2, data3);
  } catch (error) {
    console.error('Error:', error);
  }
}

// Parallel execution
async function readFilesParallel() {
  try {
    const [data1, data2, data3] = await Promise.all([
      fs.readFile('file1.txt', 'utf8'),
      fs.readFile('file2.txt', 'utf8'),
      fs.readFile('file3.txt', 'utf8')
    ]);
    
    console.log(data1, data2, data3);
  } catch (error) {
    console.error('Error:', error);
  }
}

2.4 Error Handling

2.4.1 Try-Catch

// Basic try-catch
try {
  const result = someFunction();
  console.log(result);
} catch (error) {
  console.error('Error:', error.message);
}

// Async try-catch
async function getData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Error fetching data:', error);
    throw error; // Re-throwing error
  }
}

2.4.2 Custom Errors

// Custom Error Class
class ValidationError extends Error {
  constructor(message) {
    super(message);
    this.name = 'ValidationError';
  }
}

// Menggunakan Custom Error
function validateUser(user) {
  if (!user.name) {
    throw new ValidationError('Name is required');
  }
  if (!user.email) {
    throw new ValidationError('Email is required');
  }
}

try {
  validateUser({ name: '', email: '' });
} catch (error) {
  if (error instanceof ValidationError) {
    console.error('Validation Error:', error.message);
  } else {
    console.error('Unknown Error:', error);
  }
}

2.4.3 Error Events

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();

// Error listener
myEmitter.on('error', (error) => {
  console.error('Error event:', error.message);
});

// Emit error
myEmitter.emit('error', new Error('Something went wrong'));

2.4.4 Uncaught Exceptions

// Handle uncaught exceptions
process.on('uncaughtException', (error) => {
  console.error('Uncaught Exception:', error);
  // Clean up resources
  process.exit(1);
});

// Handle unhandled promise rejections
process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Rejection:', reason);
});

2.5 Event-Driven Programming

2.5.1 Events Module

const EventEmitter = require('events');

class MyApp extends EventEmitter {
  constructor() {
    super();
    this.init();
  }

  init() {
    // Register event listeners
    this.on('start', () => {
      console.log('Application started');
    });

    this.on('data', (data) => {
      console.log('Received data:', data);
    });

    this.on('error', (error) => {
      console.error('Error:', error);
    });
  }

  start() {
    // Emit events
    this.emit('start');
    this.emit('data', { message: 'Hello World' });
  }
}

// Usage
const app = new MyApp();
app.start();

Latihan

  1. Buat program Node.js sederhana menggunakan async/await

  2. Implementasi custom error handling

  3. Buat event emitter untuk logging system

  4. Praktikkan penggunaan NPM untuk mengelola dependencies

Review

  • Node.js memberikan kemampuan untuk menjalankan JavaScript di server

  • NPM adalah tools penting untuk mengelola package dan dependencies

  • Asynchronous programming adalah konsep kunci dalam Node.js

  • Error handling yang baik penting untuk aplikasi yang robust

  • Event-driven programming memungkinkan aplikasi yang reaktif

Last updated