NodeJS Căn Bản

Ngày đăng: 2024-07-28 15:28:29

Mục lục: 

  

I. Giới thiệu về Node.js

2. Cài đặt Node.js

3. Modul trong Node.js

4. Ứng dụng Hello World 

5. REPL Terminal trong Node.js 

6. NPM trong Node.js

7. Khái niệm Callbacks trong Node.js

8. Event Loop trong Node.js

9. Event Emitter trong Node.js

10. Khái niệm Buffer trong Node.js

11. Stream trong Node.js

12 . Đọc, ghi file trong Node.js

13. Đối tượng toàn cục trong Node.js

14. Utility Module trong Node.js

 15. Web Module trong Node.js

 16. Express Framework trong Node.js

 17. RESTful API trong Node.js   

I. Giới thiệu về Node.js

A. Node.js là gì ?

NodeJS là một nền tảng Server side được xây dựng dựa trên Javascript Engine (V8 Engine). Node.js được phát triển bởi Ryan Dahl năm 2009 và phiên bản cuối cùng là v0.10.36. Định nghĩa NodeJs bởi tài liệu chính thức như sau:

Node.js là một nền tảng dựa vào Chrome Javascript runtime để xây dựng các ứng dụng nhanh, có độ lớn. Node.js sử dụng các phần phát sinh các sự kiện (event-driven), mô hình non-blocking I/O để tạo ra các ứng dụng nhẹ và hiệu quả cho các ứng dụng về dữ liệu thời gian thực chạy trên các thiết bị phân tán.

NodeJs là một mã nguồn mở, đa nền tảng cho phát triển các ứng dụng phía Server và các ứng dụng liên quan đến mạng. Ứng dụng Node.js được viết bằng Javascript và có thể chạy trong môi trường Node.js trên hệ điều hành Window, Linux...

Node.js cũng cung cấp cho chúng ta các module Javascript đa dạng, có thể đơn giản hóa sự phát triển của các ứng dụng web sử dụng Node.js với các phần mở rộng.

Node.js = Môi trường Runtime + Các thư viện Javascript

B. Đặc điểm của Node.js

Dưới đây là vài đặc điểm quan trọng biến Node.js trở thành sự lựa chọn hàng đầu trong phát triển phần mềm:

  • Không đồng bộ và Phát sinh sự kiện (Event Driven): Tất các các APIs của thư viện Node.js đều không đồng bộ, nghĩa là không blocking (khóa). Nó rất cần thiết vì Node.js không bao giờ đợi một API trả về dự liệu. Server chuyển sang một API sau khi gọi nó và có cơ chế thông báo về Sự kiện của Node.js giúp Server nhận đựa phản hồi từ các API gọi trước đó.

  • Chạy rất nhanh: Dựa trên V8 Javascript Engine của Google Chrome, thư viện Node.js rất nhanh trong các quá trình thực hiện code.

  • Các tiến trình đơn giản nhưng hiệu năng cao: Node.js sử dụng một mô hình luồng đơn (single thread) với các sự kiện lặp. Các cơ chế sự kiện giúp Server trả lại các phản hồi với một cách không khóa và tạo cho Server hiệu quả cao ngược lại với các cách truyền thống tạo ra một số lượng luồng hữu hạn để quản lý request. Nodejs sử dụng các chương trình đơn luồng và các chương trình này cung cấp các dịch vụ cho số lượng request nhiều hơn so với các Server truyền thống như Apache HTTP Server.

  • Không đệm: Ứng dụng Node.js không lưu trữ các dữ liệu buffer.

  • Có giấy phép: Node.js được phát hành dựa vào MIT License.

C. Với Node.js, bạn phải làm mọi thứ

Node.js chỉ là một môi trường – điều này có nghĩa bạn tự phải làm mọi thứ. Sẽ chẳng có bất kỳ máy chủ mặc định nào cả !!! Một đoạn script xử lý tất cả các kết nối với Client. Điều này làm giảm đáng kể số lượng tài nguyên được sử dụng trong ứng dụng.

D. Ai sử dụng Node.js

Dưới đây là link trên github wiki chứa danh sách các dự án, ứng dụng và các công ty sử dụng Node.js. Trong danh sách này bao gồm eBay, GE, GoDaddy, Microsoft, Paypal, Uber....

Các thành phần quan trọng trong Node.js

Lược đồ dưới đây mô tả các thành phần quan trọng của Node.js mà chúng ta sẽ thảo luận ở các chương tiếp theo.

Node.js là gì

Node.js được sử dụng ở đâu

Dưới đây là các lĩnh vực mà Node.js được sử dụng như là một sự lựa chọn hoàn hảo:

  • Các ứng dụng về I/O

  • Các ứng dựng về luồng dữ liệu

  • Các ứng dụng về dữ liệu hướng đến thời gian thực

  • Các ứng dụng dựa vào JSON APIs

  • Các ứng dụng Single Page Application

Node.js không nên sử dụng ở đâu:

Nó không nên sử dụng trong các ứng dụng đòi hỏi về CPU.

2. Cài đặt Node.js

A. Cài đặt Node.js nội bộ

Nếu bạn muốn thiết lập môi trường node.js trên máy tính cá nhân, bạn phải có 2 phần mềm trên máy tính của bạn. Đó là: 1)Text Editor (ví dụ : Nodepad++); 2) bộ cài binary Nodejs.

Text Editor

Nó sẽ được sử dụng để soạn thảo chương trình của bạn. Ví dụ một vài Editor trên Windows như Nodepad, vi hoặc vim (trên Linux)...

File mà bạn tạo ra trên editor của bạn gọi là source file (file nguồn) và chứa các chương trình mã nguồn. Các file nguồn cho Node.js thường được đặt tên với định dạng mở rộng ".js" 

Trước khi bắt đầu chương trình này, phải chắc chắn là bạn đã có một text editro được sử dụng và có kinh nghiệm trong việc viết các chương trình trong máy tính, lưu trữ file và thực thi nó.

B. Cài đặt Node.js Runtime

Source code của bạn được viết bởi các đoạn Javascript đơn giản. Trình thông dịch Node.js sẽ được sử dụng để biên dịch và thực thi các đoạn mã Javascript.

Các phiên bản cài đặt Nodejs có sẵn cho các Hệ điều hành 32-bit và 64 bit của Linux, Mac, Window...

Phần dưới trình bày các bước để cài đặt Node.js binary trên các Hệ điều hành khác nhau.

Download Node.js

Download phiên bản mới nhất của Node.js từ trang Node.js Downloads. Tại thời điểm bài hướng dẫn này, các phiên bản mới nhất tương ứng với các hệ điều hành như sau:

OS Archive name
Windows node-v0.12.0-x64.msi
Linux node-v0.12.0-linux-x86.tar.gz
Mac node-v0.12.0-darwin-x86.tar.gz
SunOS node-v0.12.0-sunos-x86.tar.gz

Cài đặt Node.js trên UNIX/Linux/Mac OS X, và SunOS

Dựa vào các kiến trúc của các hệ điều hành, tải và giải nén node-v0.12.0-osname.tar.gz trong thư mục /tm và sau cùng là giải nén vào thư mục /usr/local/nodejs. Ví dụ:

$ sudo apt-get install nodejs

Thêm /usr/local/nodejs/bin vào biến môi trường PATH:

OS Kết quả
Linux export PATH=/usr/local/nodejs/bin
Mac export PATH=$PATH:/usr/local/nodejs/bin
FreeBSD export PATH=$PATH:/usr/local/nodejs/bin

Cài đặt Node.js trên Windows

Sử dụng file MSI và theo các hướng dẫn hiện lên khi cài đặt Node.js. Mặc định, bộ cài đặt Node.js được lưu trữ tại C:\Program Files\nodejs .

Xác nhận quá trình cài đặt Node.js có thành công không

Tạo một file js với tên main.js trên máy tính (Windows hoặc Linux) với dòng code dưới đây:

/* Hello, World! Vi du kiem tra cai dat node.js */
console.log("Hello, World!")

Bây giờ thực hiện main.js sử dụng trình biên dịch Node.js để xem các kết quả:

$ node main.js

Nếu mọi thứ thành công, sau khi biên dịch sẽ cho kết quả:

Hello, World!

3. Modul trong Node.js

A. Module trong Node.js

Node.js sử dụng kiến trúc Module để đơn giản hóa việc tạo ra các ứng dụng phức tạp. Module là giống như các thư viện trong C, C#, Java, … Mỗi module chứa một tập các hàm chức năng có liên quan đến một "đối tượng" của Module. Ví dụ, http là Module chứa các hàm cụ thể liên quan đến thiết lập HTTP. Node.js cung cấp một vài các Module core kèm theo để hỗ trợ chúng ta truy cập file trên hệ thống, tạo các máy chủ HTTP, TCP/UDP, và các hàm tiện ích nhỏ hữu dụng khác.

Trước khi sử dụng Module, bạn đơn giản chỉ cần khai báo với hàm require(), như sau:

var http = require("http");

Node.js chỉ là môi trường, bạn phải tự làm mọi thứ!

require() là hàm trả về tham chiếu tới một Module cụ thể. Trong trường hợp của đoạn mã trên, chúng ta đang khai báo một tham chiếu tới http Module và lưu nó vào biến http.

Trong đoạn mã trên, chúng truyền một tham số là tên của Module. Điều này báo cho Node sẽ tìm một Module tên là http trong thư mục node_modules của ứng dụng. Nếu nó không thấy, Node sẽ tiếp tục tìm Module đó ở thư mục global cài đặt node.

Lệnh kiểm tra thư mục global cài đặt node_modules, bạn mở giao diện dòng lệnh CMD và gõ lệnh sau:

npm root -g

Quay trở lại vấn đề, bạn có thể chỉ rõ file bằng việc truyền vào tham số là đường dẫn tương đối ./path/to/my/module.js hoặc tuyệt đối /path/to/my/module.js

var myModule = require('./myModule.js')

Tóm lại, Module là các đoạn mã được đóng gói lại với nhau. Mã trong một Module thường là private – nghĩa là các hàm, biến được định nghĩa và truy cập bởi bên trong của Module. Nhưng, bạn có thể chìa ra các api là các hàm và/hoặc biến để sử dụng bên ngoài Module. Bằng cách sử dụng 1 đối tượng exports, xem ví dụ sau đây:

var PI = Math.PI;
  
exports.dientich = function (r) {
  return PI * r * r;
};
  
exports.chuvi = function (r) {
  return 2 * PI * r;
};

Đoạn mã trên tạo ra một biến PI và nó chỉ có thể truy cập trong Module ta đang định nghĩa. Bằng việc sử dụng exports để chìa ra 2 hàm sử dụng bên ngoài Module là dientich() và chuvi() . Như vậy, giả sử ta đang viết mã trên file ./myModule.js thì biến khai báo tham chiếu myModule có thể gọi hàm dientich() và chuvi()

B. Global Scope trong Node.js

Node.js là môi trường cho phép lập trình sử dụng JavaScript ở phía server và chạy trên Google's V8 JavaScript engine. Như vậy, chúng ta nên thực hiện các đoạn mã như khi sử dụng lập trình ở phía Client. Ví dụ, chúng ta nên hạn chế sử dụng biến global. Tuy nhiên, nếu muốn sử dụng, bạn có thể dễ dàng tạo một biến global bằng việc định nghĩa tên biến không có từ khóa var, như sau:

globalVariable = 1;
globalFunction = function () { ... };

Một lần nữa, biến global nên được hạn chế đến mức tối đa. Vì thế, hãy cần thận và nhớ sử dụng từ khóa var để khai báo biến.

4. Ứng dụng Hello World

Trước khi tạo ứng dụng thực tế "Hello world" trong Node.js, cùng xem các phần chính của chương trình Node.js. Một chương trình Node.js bao gồm các phần quan trọng đưới đây:

  • Các Module cần thiết: Chúng ta sử dụng require directive để tải một Node.js module.

  • Tạo Server: Một Server lắng nghe yêu cầu từ phía client tương tự như các Server Apache HTTP.

  • Đọc request và trả về các response: Server được tạo một các dễ dàng bên trên sẽ đọc các HTTP request bởi client từ các trình duyệt hay màn hình console để trả về các phản hồi.

A. Tạo ứng dụng Node.js

Bước 1: Import các Module cần thiết

Chúng ta sử dụng require directive để tải các Module http và trả về các sự thể hiện đến biến http như sau:

var http = require("http");

Bước 2: Tạo Server

Bước tiếp theo, chúng ta sẽ tạo http và gọi phương thức http.createServer() để tạo mới một Server và trả về một Server Instance và sau đó gắn kết nó trên cổng 8081. Truyền vào nó với các tham số request và response. Viết đoạn ví dụ sau đây về chương trình "Hello World".

http.createServer(function (request, response) {

   // Gui HTTP header cua request
   // HTTP Status: 200 : OK
   // Content Type: text/plain
   response.writeHead(200, {'Content-Type': 'text/plain'});
   
   // Gui phan than cua response, bao gom "Hello World"
   response.end('Hello World\n');
}).listen(8081);

// Man hinh Console se in thong bao
console.log('Server dang chay tai http://127.0.0.1:8081/');

Đoạn code này đủ cho việc tạo một HTTP Server để lắng nghe và đợi các phản hồi trên 8081 của máy local.

Bước 3: Kiểm tra Request & Response

Cùng đặt bước 1 và 2 với nhau trong 1 file với tên gọi main.js và bật HTTP Server như sau:

var http = require("http");

http.createServer(function (request, response) {

   // Gui HTTP header cua request
   // HTTP Status: 200 : OK
   // Content Type: text/plain
   response.writeHead(200, {'Content-Type': 'text/plain'});
   
   // Gui phan than cua response, bao gom "Hello World"
   response.end('Hello World\n');
}).listen(8081);

// Man hinh Console se in thong bao
console.log('Server dang chay tai http://127.0.0.1:8081/');

Start Server và xem kết quả như sau:

$ node main.js

Kiểm tra kết quả. Server đã được bật.

Server dang chay tai http://127.0.0.1:8081/

C. Tạo một request đến một Node.js Server

Mở http://127.0.0.1:8081/ trong bất kỳ trình duyệt nào và xem kết quả:.

Ứng dụng Hello World trong Node.js

5. REPL Terminal trong Node.js

REPL là từ viết tắt của Read Eval Print Loop (hiểu nôm na là: Đọc - Đánh giá - In - Lặp) và nó biểu diễn môi trường máy tính như màn hình console trong Linux shell nơi bạn có thể gõ các dòng lệnh và hệ thống sẽ trả về các kết quả. Node.js cũng có môi trường REPL. Nó để thực hiện các tác vụ mong muốn:

  • Read: Đọc các thông tin input của người dùng, chuyển đổi thành các dữ liệu Javascript và lưu trữ trong bộ nhớ.

  • Eval: Đánh giá các cấu trúc dữ liệu này.

  • Print: In các kết quả.

  • Loop: Lặp các dòng lệnh đến khi người dùng gõ ctrl-c hai lần.

Đặc tính REPL của Node js rất hữu ích khi bạn sử dụng Node.js với mục đích debug code.

A. Bắt đầu với REPL trong Node.js

REPL có thể bắt đầu bằng cách đơn giản trên màn hình shell/console mà không sử dụng bất cứ tham số nào như sau:

$ node

Bạn sẽ thấy màn hình dòng nhắc lệnh REPL >. Tại đây, bạn có thể gõ bất cứ lệnh nào trong Node.js.

$ node
>

B. Các biểu thức đơn giản trong Node.js

Dưới đây mình giới thiệu một số biểu thức đơn giản có thể được sử dụng tại dòng nhắc lệnh REPL trong Node.js:

$ node
> 1 + 3
4
> 1 + ( 2 * 3 ) - 4
3
>

C. Sử dụng biến trong Node.js

Bạn có thể sử dụng các biến để lưu trữ giá trị và sau đó in giá trị của biến giống như trong các đoạn mã truyền thống. Nếu không sử dụng từ khóa var, giá trị sẽ được lưu trữ trong biến và in ra. Trong khi đó nếu từ khóa var được sử dụng, giá trị được lưu trữ và có thể không được in. Bạn có thể in biến sử dụng console.log().

$ node
> x = 10
10
> var y = 10
undefined
> x + y
20
> console.log("Hello World")
Hello World
undefined

D. Biểu thức trên nhiều dòng trong Node.js

Node REPL hỗ trợ dạng biểu thức nằm trên nhiều dòng tương tự như trong Javascript. Cùng kiểm tra biểu thức do-while trong hành động sau đây:

$ node
> var x = 0
undefined
> do {
... x++;
... console.log("x: " + x);
... } while ( x < 5 );
x: 1
x: 2
x: 3
x: 4
x: 5
undefined
>

Các dấu gạch chấm ... hiển thị tự động khi bạn nhấn phím Enter sau dấu ngoặc mở. Node.js sẽ tự động kiểm tra xem biểu thức có được tiếp tục nữa hay không.

E. Biến có dấu gạch dưới trong Node.js

Bạn có thể sử dụng dấu gạch dưới _ để nhận kết quả cuối cùng của phép tính:

$ node
> var x = 10
undefined
> var y = 20
undefined
> x + y
30
> var sum = _
undefined
> console.log(sum)
30
undefined
>

F. Giới thiệu một số lệnh REPL trong Node.js

  • ctrl + c - Kết thúc lệnh hiện tại.

  • Nhấn ctrl + c hai lần - Kết thúc Node REPL.

  • ctrl + d - Kết thúc Node REPL.

  • Các phím mũi tên Up/Down - Xem lịch sử các lệnh, kiểm tra lệnh trước đó và có thể sửa đổi các lệnh đã soạn trước đó.

  • Phím tab - Danh sách các lệnh hiện tại.

  • .help - Danh sách tất cả các lệnh.

  • .break - Thoát khỏi một biểu thức nằm trên nhiều dòng (ví dụ: do-while).

  • .clear - Thoát khỏi một biểu thức nằm trên nhiều dòng

  • .save ten_file - Lưu phiên làm việc của Node.js REPL hiện tại vào một ten_file nào đó.

  • .load ten_file - Tải nội dung của ten_file của phiên làm việc Node.js REPL hiện tại.

6. NPM trong Node.js

NPM là viết tắt của Node Package Manager cung cấp hai chức năng sau:

  • Tạo các online repository cho node.js mà có thể tìm kiếm được tại địa chỉ search.nodejs.org

  • Cung cấp các tiện ích để cài đặt gói Node.js, quản lí version và quản lí phụ thuộc của các gói trong Node.js.

NPM được đóng gói cùng với Node.js từ phiên bản v0.6.3. Để xác nhận việc này, mở cửa sổ dòng lệnh, gõ những lệnh sau và xem kết quả:

$ npm --version
2.7.1

Nếu bạn chạy các hệ thống cũ của npm, có thể dễ dàng cập nhật bản mới nhất. Sử dụng lệnh sau đây dưới quyền root:

$ sudo npm install npm -g
/usr/bin/npm -> /usr/lib/node_modules/npm/bin/npm-cli.js
npm@2.7.1 /usr/lib/node_modules/npm

A. Cài đặt các Module bởi sử dụng npm trong Node.js

Dưới đây là cú pháp đơn giản để cài đặt bất kỳ Node.js Module nào:

$ npm install <Module Name>

Ví dụ: Dưới đây là lệnh để cài đặt một module rất phổ biến trong Node.js, đó là express Module:

$ npm install express

Bây giờ để sử dụng môđun này trong file js của bạn, sử dụng cú pháp sau đây:

var express = require('express');

B. Cài đặt Global và cài đặt local

Mặc định, npm cài đặt bất kì phụ thuộc nào trên máy tính local. Ở đây, module này hướng đến các gói cài đặt trong thư mục node_modules trong thư mục ứng dụng của Node. Gói local này có thể triển khai dựa vào phương thức require(). Ví dụ, khi bạn cài đặt Module express, bạn tạo thư mục node_modules trong thư mục hiện tại nơi bạn có thể cài đặt Module này.

$ ls -l
total 0
drwxr-xr-x 3 root root 20 Mar 17 02:23 node_modules

Cách khác, bạn có thể sử dụng lệnh npm ls để liệt kê các thư mục Module cài đặt.

Gói cài đặt toàn cục được lưu trữ trong các file hệ thống. Các phụ thuộc có thể được sử dụng với các hàm CLI (Command Line Interface) của node.js nhưng không thể import sử dụng require() của ứng dụng Node một cách trực tiếp.

Bây giờ cùng thử cài đặt Module express sử dụng cài đặt toàn cục như sau:

$ npm install express -g

Điều này sẽ cho kết quả tương tự nhưng Module được cài đặt toàn cục. Ở đây, dòng đầu tiên nói với chúng ta về Module version và nơi chứa các bộ cài khi bắt đầu.

express@4.12.2 /usr/lib/node_modules/express
├── merge-descriptors@1.0.0
├── utils-merge@1.0.0
├── cookie-signature@1.0.6
├── methods@1.1.1
├── fresh@0.2.4
├── cookie@0.1.2
├── escape-html@1.0.1
├── range-parser@1.0.2
├── content-type@1.0.1
├── finalhandler@0.3.3
├── vary@1.0.0
├── parseurl@1.3.0
├── content-disposition@0.5.0
├── path-to-regexp@0.1.3
├── depd@1.0.0
├── qs@2.3.3
├── on-finished@2.2.0 (ee-first@1.1.0)
├── etag@1.5.1 (crc@3.2.1)
├── debug@2.1.3 (ms@0.7.0)
├── proxy-addr@1.0.7 (forwarded@0.1.0, ipaddr.js@0.1.9)
├── send@0.12.1 (destroy@1.0.3, ms@0.7.0, mime@1.3.4)
├── serve-static@1.9.2 (send@0.12.2)
├── accepts@1.2.5 (negotiator@0.5.1, mime-types@2.0.10)
└── type-is@1.6.1 (media-typer@0.3.0, mime-types@2.0.10)

Bạn cũng có thể sử dụng lệnh sau đây để kiểm tra các phiên bản cài đặt toàn cục:

$ npm ls -g

C. Sử dụng gói package.json

Package.json hiển thị trong thư mục root của bất cứ ứng dụng Node nào và được sử dụng để định nghĩa thuộc tính của gói. Cùng mở một file package.json của gói express hiển thị trong node_modules/express/:

{
  "name": "express",
  "description": "Fast, unopinionated, minimalist web framework",
  "version": "4.11.2",
  "author": {
    "name": "TJ Holowaychuk",
    "email": "tj@vision-media.ca"
  },
  "contributors": [
    {
      "name": "Aaron Heckmann",
      "email": "aaron.heckmann+github@gmail.com"
    },
    {
      "name": "Ciaran Jessup",
      "email": "ciaranj@gmail.com"
    },
    {
      "name": "Douglas Christopher Wilson",
      "email": "doug@somethingdoug.com"
    },
    {
      "name": "Guillermo Rauch",
      "email": "rauchg@gmail.com"
    },
    {
      "name": "Jonathan Ong",
      "email": "me@jongleberry.com"
    },
    {
      "name": "Roman Shtylman",
      "email": "shtylman+expressjs@gmail.com"
    },
    {
      "name": "Young Jae Sim",
      "email": "hanul@hanul.me"
    }
  ],
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/strongloop/express"
  },
  "homepage": "http://expressjs.com/",
  "keywords": [
    "express",
    "framework",
    "sinatra",
    "web",
    "rest",
    "restful",
    "router",
    "app",
    "api"
  ],
  "dependencies": {
    "accepts": "~1.2.3",
    "content-disposition": "0.5.0",
    "cookie-signature": "1.0.5",
    "debug": "~2.1.1",
    "depd": "~1.0.0",
    "escape-html": "1.0.1",
    "etag": "~1.5.1",
    "finalhandler": "0.3.3",
    "fresh": "0.2.4",
    "media-typer": "0.3.0",
    "methods": "~1.1.1",
    "on-finished": "~2.2.0",
    "parseurl": "~1.3.0",
    "path-to-regexp": "0.1.3",
    "proxy-addr": "~1.0.6",
    "qs": "2.3.3",
    "range-parser": "~1.0.2",
    "send": "0.11.1",
    "serve-static": "~1.8.1",
    "type-is": "~1.5.6",
    "vary": "~1.0.0",
    "cookie": "0.1.2",
    "merge-descriptors": "0.0.2",
    "utils-merge": "1.0.0"
  },
  "devDependencies": {
    "after": "0.8.1",
    "ejs": "2.1.4",
    "istanbul": "0.3.5",
    "marked": "0.3.3",
    "mocha": "~2.1.0",
    "should": "~4.6.2",
    "supertest": "~0.15.0",
    "hjs": "~0.0.6",
    "body-parser": "~1.11.0",
    "connect-redis": "~2.2.0",
    "cookie-parser": "~1.3.3",
    "express-session": "~1.10.2",
    "jade": "~1.9.1",
    "method-override": "~2.3.1",
    "morgan": "~1.5.1",
    "multiparty": "~4.1.1",
    "vhost": "~3.0.0"
  },
  "engines": {
    "node": ">= 0.10.0"
  },
  "files": [
    "LICENSE",
    "History.md",
    "Readme.md",
    "index.js",
    "lib/"
  ],
  "scripts": {
    "test": "mocha --require test/support/env --reporter spec --bail --check-leaks test/ test/acceptance/",
    "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require test/support/env --reporter dot --check-leaks test/ test/acceptance/",
    "test-tap": "mocha --require test/support/env --reporter tap --check-leaks test/ test/acceptance/",
    "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require test/support/env --reporter spec --check-leaks test/ test/acceptance/"
  },
  "gitHead": "63ab25579bda70b4927a179b580a9c580b6c7ada",
  "bugs": {
    "url": "https://github.com/strongloop/express/issues"
  },
  "_id": "express@4.11.2",
  "_shasum": "8df3d5a9ac848585f00a0777601823faecd3b148",
  "_from": "express@*",
  "_npmVersion": "1.4.28",
  "_npmUser": {
    "name": "dougwilson",
    "email": "doug@somethingdoug.com"
  },
  "maintainers": [
    {
      "name": "tjholowaychuk",
      "email": "tj@vision-media.ca"
    },
    {
      "name": "jongleberry",
      "email": "jonathanrichardong@gmail.com"
    },
    {
      "name": "shtylman",
      "email": "shtylman@gmail.com"
    },
    {
      "name": "dougwilson",
      "email": "doug@somethingdoug.com"
    },
    {
      "name": "aredridel",
      "email": "aredridel@nbtsc.org"
    },
    {
      "name": "strongloop",
      "email": "callback@strongloop.com"
    },
    {
      "name": "rfeng",
      "email": "enjoyjava@gmail.com"
    }
  ],
  "dist": {
    "shasum": "8df3d5a9ac848585f00a0777601823faecd3b148",
    "tarball": "http://registry.npmjs.org/express/-/express-4.11.2.tgz"
  },
  "directories": {},
  "_resolved": "https://registry.npmjs.org/express/-/express-4.11.2.tgz",
  "readme": "ERROR: No README data found!"
}

D. Các thuộc tính của Package.json

  • name - tên của package

  • version - phiên bản của package

  • description - phần mô tả của package

  • homepage - trang chủ của package

  • author - tác giả của package

  • contributors - tên người đóng góp cho package

  • dependencies - Danh sách các gói phụ thuộc, tự động được cài theo.

  • repository - loại repository và url của package

  • main - điểm vào của package

  • keywords - các từ khóa

E.Gỡ cài đặt một module trong Node.js

Sử dụng các dòng lệnh dưới đây để gỡ một Module trong Node.js

$ npm uninstall express

Khi gỡ cài đặt gói này, bạn có thể xác nhận nội dung trong thư mục /node_modules/ bằng cách sử dụng lệnh sau đây:

$ npm ls

F. Cập nhật một Module trong Node.js

Cập nhật gói package.json và thay đổi phiên bản của các ràng buộc mà có thể cập nhật sử dụng lệnh sau đây:

$ npm update express

G. Tìm kiếm một Module trong Node.js

Sử dụng npm, bạn có thể tìm kiếm một Module như sau:

$ npm search express

H.Tạo một Module trong Node.js

Quá trình tạo Module yêu cầu gói package.json được tạo ra.

$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sane defaults.

See 'npm help json' for definitive documentation on these fields
and exactly what they do.

Use 'npm install <pkg> --save' afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (webmaster)

Bạn cần cung cấp tất cả các thông tin được yêu cầu trong việc sử dụng Module. Bạn có thể sử dụng các bước bên trên trong file package.json để hiểu về ý nghĩa của các thông tin yêu cầu. Khi gói package.json được tạo ra, sử dụng các lệnh dưới đây đăng ký với trang npm bởi sử dụng địa chỉ email hợp lệ.

$ npm adduser
Username: mcmohd
Password:
Email: (this IS public) mcmohd@gmail.com

Bây giờ publish Module của bạn:

$ npm publish

Nếu mọi thứ tốt đẹp, nó sẽ được publish và thư mục này sẽ được truy cập bởi những người khác sử dụng Module Node.js

7. Khái niệm Callbacks trong Node.js

A. Callback là gì ?

Callback có tính chất không đồng bộ tương đương cho một hàm. Một hàm callback được gọi khi hoàn thành một nhiệm vụ cụ thể. Tất cả các API của Node đều được viết theo các cách của hàm callback.

Ví dụ, một hàm để đọc file bắt đầu với việc đọc file và trả về phần điều khiển để môi trường thực hiện quyết định lệnh tiếp theo có thể thực thi. Khi phần I/O (đọc/ghi) file được hoàn thành, nó sẽ gọi về một hàm callback, với nội dung của file là tham số. Do đó sẽ không có blocking hoặc chờ khi đọc/ghi File. Nó làm cho Node.js có hiệu năng cao hơn, như có số lượng request cao hơn mà không cần phải chờ kết quả trả về.

B. Ví dụ Blocking Code

Tạo một dòng text với tên input.txt với nội dung sau đây

VietJack la trang Web huong dan cac bai lap trinh
hoan toan mien phi cho tat ca moi nguoi!!!!!

Tạo một file js với tên main.js với nội dung sau đây:

var fs = require("fs");

var data = fs.readFileSync('input.txt');

console.log(data.toString());
console.log("Ket thuc chuong trinh");

Bây giờ chạy lệnh sau để xem kết quả:

$ node main.js

Kết quả:

VietJack la trang Web huong dan cac bai lap trinh
hoan toan mien phi cho tat ca moi nguoi!!!!!
Ket thuc chuong trinh

C. Ví dụ Non-Blocking Code

Tạo một file với tên input.txt với nội dung sau đây:

VietJack la trang Web huong dan cac bai lap trinh
hoan toan mien phi cho tat ca moi nguoi!!!!!

Cập nhật main.js với dòng code sau:

var fs = require("fs");

fs.readFile('input.txt', function (err, data) {
    if (err) return console.error(err);
    console.log(data.toString());
});

console.log("Ket thuc chuong trinh");

Bây giờ chạy main.js để xem kết quả:

$ node main.js

Kết quả:

Ket thuc chuong trinh
VietJack la trang Web huong dan cac bai lap trinh
hoan toan mien phi cho tat ca moi nguoi!!!!!

Hai ví dụ trên giải thích định nghĩa cách gọi blocking và non-blocking. Ví dụ đầu tiên chỉ ra rằng chương trình khóa cho đến khi nó đọc file và chỉ tiếp tục chạy vài giây sau đó, chương trình thứ 2 không đợi cho việc đọc file và tiếp tục in "Ket thuc chuong trinh" cùng thời điểm thực hiện chương trình.

8. Event Loop trong Node.js

Node.js là ứng dụng đơn luồng nhưng có hỗ trợ việc xử lí đồng thời thông qua các định nghĩa về sự kiện và callback. Như tất cả các API của Node.js có tính chất không đồng bộ và được xử lí đơn luồng, nó sử dụng hàm async để duy trì sự đồng thời. Node.js sử dụng Observer Pattern. Các Thread trong Node.js giữ một Event Loop và bất cứ khi nào có tác vụ nào hoàn thành, nó sẽ kích hoạt sự kiện tương ứng để báo cho Event Listener sẵn sàng thực hiện..

A. Lập trình Event Driven trong Node.js

Node.js sử dụng rất nhiều sự kiện, đó là lý do tại sao Node.js khá nhanh so với các sản phẩm công nghệ khác. Ngay khi Node khởi động Server của nó, nó sẽ nhanh chóng khởi tạo các biến, khai báo các hàm và sau đó đơn giản là chờ đợi các sự kiện xảy ra.

Trong ứng dụng xử lý sự kiện, nhìn chung vòng lặp chính lắng nghe các sự kiện, và sau đó trigger đến hàm callback khi một trong những sự kiện được phát hiện.

Event Loop trong Node.js

Trong khi các Event là khá tương tự như các hàm callback . Điểm khác nhau nằm ở chỗ, hàm callback gọi khi một hàm không đồng bộ và trả về kết quả của nó trong khi phần xử lí sự kiện làm việc trên Observer Pattern. Hàm này sẽ lắng nghe các sự kiện, đóng vai trò như một Observers (Người quan sát). Bất cứ khi nào một sự kiện phát sinh, các hàm Listener của nó sẽ bắt đầu thực thi. Node.js có nhiều sự kiện có sẵn thông qua events Module và lớp EventEmitter có thể dựa vào để bind sự kiện và lắng nghe sự kiện.

Trước khi sử dụng event Module, bạn sử dụng phương thức require() để khai báo như sau:

// Khai bao events module
var events = require('events');

// Tao mot doi tuong eventEmitter
var eventEmitter = new events.EventEmitter();

Sau đó, để gắn kết Event Handler với một sự kiện, bạn sử dụng cú pháp sau:

// Gan ket event voi Event Handler nhu sau:
eventEmitter.on('eventName', eventHandler);

Bạn có thể kích hoạt một sự kiện bởi sử dụng phương thức emit() của EventEmitter:

// Kich hoat mot event 
eventEmitter.emit('eventName');

B. Ví dụ minh họa Event Loop trong Node.js

Tạo một file js với tên là main.js có đoạn code sau:

// Khai bao events module
var events = require('events');
// Tao mot doi tuong eventEmitter
var eventEmitter = new events.EventEmitter();

// Tao mot Event Handler nhu sau:
var connectHandler = function connected() {
   console.log('Tao ket noi thanh cong!');
  
   // Kich hoat su kien data_received 
   eventEmitter.emit('data_received');
}

// Gan ket su kien connection voi Event Handler
eventEmitter.on('connection', connectHandler);
 
// Gan ket su kien data_received voi mot ham an danh
eventEmitter.on('data_received', function(){
   console.log('Du lieu duoc tiep nhan thanh cong.');
});

// Kich hoat su kien connection 
eventEmitter.emit('connection');

console.log("Ket thuc chuong trinh.");

Chạy chương trình trên như sau:

$ node main.js

Kết quả là:

Tao ket noi thanh cong!
Du lieu duoc tiep nhan thanh cong.
Ket thuc chuong trinh.

C. Cách ứng dụng Node.js hoạt động

Trong ứng dụng Node.js, một hàm không đồng bộ chấp nhận một callback như tham số cuối cùng và hàm callback chấp nhận error như tham số đầu tiên. Cùng xem lại ví dụ trước. Tạo một text file với tên input.txt với nội dung sau đây:

Titoe.net la trang Web huong dan cac bai lap trinh
hoan toan mien phi cho tat ca moi nguoi!!!!!

Trong ví dụ này, mình sử dụng fs Module để xử lý các hoạt động File I/O (mình sẽ trình bày trong chương sau). Đầu tiên, bạn tạo một file js với tên là main.js như sau:

var fs = require("fs");

fs.readFile('input.txt', function (err, data) {
   if (err){
      console.log(err.stack);
      return;
   }
   console.log(data.toString());
});
console.log("Ket thuc chuong trinh");

Ở đây, fs.readFile() là một hàm không đồng bộ với mục đích để đọc file. Nếu có một lỗi nào đó trong quá trình đọc file, đối tượng err sẽ chứa lỗi đó, nếu không thì data sẽ chứa các phần nội dung của file đó. Hàm readFile truyền err và data đến hàm callback sau khi quá trình đọc file đã hoàn thành, và cuối cùng sẽ in ra nội dung.

9. Event Emitter trong Node.js

Nhiều đối tượng trong Node.js sinh ra các sự kiện, ví dụ net.Server sinh ra một sự kiện mỗi khi có một kết nối ngang hàng đến nó, hay fs.readStream sinh ra sự kiện khi một file được mở. Tất cả các đối tượng này đều là sự thể hiện của lớp events.EventEmitter trong Node.js.

A.Lớp EventEmitter trong Node.js

Lớp EventEmitter nằm trong events Module. Lớp này được truy cập qua cú pháp sau:

// Khai bao events Module
var events = require('events');
// Tao mot doi tuong eventEmitter
var eventEmitter = new events.EventEmitter();

Khi một EventEmitter gặp bất kì lỗi nào, nó sẽ sinh ra một Error Event. Khi một Listener mới được thêm, sự kiện 'newListener' sẽ được kích hoạt và một Listener sẽ bị loại bỏ, sự kiện 'removeListener' sẽ được kích hoạt.

Event Emitter cung cấp nhiều thuộc tính như on hay emit. Thuộc tính on được sử dụng để gắn kết một hàm với sự kiện, và emit dược sử dụng để kích hoạt một sự kiện.

B. Các phương thức của lớp EventEmitter trong Node.js

Stt Phương thức & Miêu tả
1 addListener(event, listener)
Thêm một Listener vào phần cuối của mảng các Listener cho một sự kiện cụ thể
2 on(event, listener)
Thêm một Listener vào phần cuối của mảng các Listener cho một sự kiện cụ thể
3 once(event, listener)
Thêm một One-Time Listener cho sự kiện. Listener dạng này sẽ chỉ được gọi khi sự kiện được kích hoạt, sau đó nó sẽ bị xóa
4 removeListener(event, listener)
Xóa một Listener ra khỏi mảng các Listener cho một sự kiện nào đó.
5 removeAllListeners([event])
Xóa tất cả Listener của một sự kiện
6 setMaxListeners(n)
Theo mặc định, lớp EventEmitters sẽ in một lời cảnh báo nếu bạn thêm nhiều hơn 10 Listener cho một sự kiện cụ thể. Việc này khá hữu ích, bởi vì nó sẽ giúp tìm ra các lỗi gây rò rỉ bộ nhớ. Tất nhiên, không phải tất cả các Emitters đều cần được giới hạn với con số là 10. Hàm này cho phép bạn tăng con số đó. Thiết lập nó về 0 để không giới hạn lượng Listener cần thêm
7 listeners(event)
Trả về một mảng bao gồm các Listener cho một sự kiện cụ thể nào đó
8 emit(event, [arg1], [arg2], [...])
Thực thi từng Listener với các tham số đã cho. Trả về true nếu sự kiện có các Listener, và false nếu không có

C. Các sự kiện của lớp EventEmitter trong Node.js

Stt Sự kiện & Miêu tả
1 newListener
  • event - Dạng chuỗi, biểu diễn tên sự kiện

  • listener - Tên hàm xử lý sự kiện

Sự kiện này được sinh bất cứ khi nào bạn thêm một Listener. Khi sự kiện này được kích hoạt, Listener có thể sẽ chưa được thêm vào mảng Listener của sự kiện

2 removeListener
  • event - Dạng chuỗi, biểu diễn tên sự kiện

  • listener - Tên hàm xử lý sự kiện

Sự kiện này xảy ra bất cứ khi nào có ai đó xóa một Listener. Khi một sự kiện được kích hoạt, Listener này chưa được xóa khỏi mảng Listener của sự kiện

D. Ví dụ minh họa lớp EventEmitter trong Node.js

Tạo một file js với tên là main.js với nội dụng Node.js như dưới đây. Trong main.js, đầu tiên bạn khai báo events Module bởi sử dụng phương thức require(). Tiếp đó, bạn sử dụng phương thức addListener() để thêm một Listener cho một sự kiện nào đó, và sử dụng các thuộc tính on và emit để thực hiện các tính năng đã trình bày ở trên.

var events = require('events');
var eventEmitter = new events.EventEmitter();

// listener #1
var listner1 = function listner1() {
   console.log('listener1 duoc thuc thi.');
}

// listener #2
var listner2 = function listner2() {
  console.log('listener2 duoc thuc thi.');
}

// Gan ket su kien connection voi ham listner1
eventEmitter.addListener('connection', listner1);

// Gan ket su kien connection voi ham listner2
eventEmitter.on('connection', listner2);

var eventListeners = require('events').EventEmitter.listenerCount(eventEmitter,'connection');
console.log(eventListeners + " Event Listner dang lang nghe su kien connection");

// Fire the connection event 
eventEmitter.emit('connection');

// Remove the binding of listner1 function
eventEmitter.removeListener('connection', listner1);
console.log("Bay gio, Listner1 se khong lang nghe.");

// Fire the connection event 
eventEmitter.emit('connection');

eventListeners = require('events').EventEmitter.listenerCount(eventEmitter,'connection');
console.log(eventListeners + " Event Listner dang lang nghe su kien connection");

console.log("Ket thuc chuong trinh.");

Chạy main.js để xem kết quả:

$ node main.js

Kiểm tra kết quả:

2 Event Listner dang lang nghe su kien connection
listener1 duoc thuc thi.
listener2 duoc thuc thi.
Bay gio, Listner1 se khong lang nghe.
listener2 duoc thuc thi.
1 Event Listner dang lang nghe su kien connection
Ket thuc chuong trinh.

10. Khái niệm Buffer trong Node.js

Javascript thuần được mã hóa Unicode một cách tiện lợi nhưng không thật sự tốt với các dữ liệu nhị phân. Khi làm việc với các luồng TCP hoặc hệ thống file, cần thiết phải xử lý các luồng dữ liệu bát phân. Node.js cung cấp các lớp Buffer cho phép lưu trữ các dữ liệu thô như một mảng các số nguyên tương ứng với phần cấp phát bộ nhớ thô bên ngoài V8 heap.

Các lớp Buffer trong Node.js là các lớp toàn cục và có thể được truy cập trong ứng dụng mà không cần khai báo các Buffer Module bởi phương thức require() như các Module khác.

A. Tạo các Buffer trong Node.js

Buffer trong Node.js có thể được xây dựng theo nhiều cách khác nhau.

Cách 1

Cú pháp cho việc tạo một Buffer cỡ 10:

var buf = new Buffer(10);

Cách 2

Cú pháp tạo một Buffer từ một mảng cho trước:

var buf = new Buffer([10, 20, 30, 40, 50]);

Cách 3

Cú pháp tạo một Buffer từ một chuỗi cho trước và với kiểu mã hóa tùy ý:

var buf = new Buffer("Hoc Nodejs tai Titoe.net", "utf-8");

Mặc dù "utf8" là cách mã hóa mặc định nhưng bạn có thể sử dụng các cách mã hóa khác như "ascii", "utf8","base64", …

B. Ghi dữ liệu vào Buffer trong Node.js

Cú pháp

Cú pháp để ghi một Buffer trong Node.js là:

buf.write(string[, offset][, length][, encoding])

Chi tiết về tham số

  • string - Đây là một dữ liệu dạng chuỗi được ghi tới buffer.

  • offset - Đây là chỉ mục để buffer bắt đầu ghi tại đó. Giá trị mặc định là số 0.

  • length - Số lượng các byte được ghi. Mặc định là buffer.length.

  • encoding - Mã hóa được sử dụng. "utf8" là mã hóa mặc định.

Giá trị trả về

Phương thức sẽ trả về số lượng các byte được ghi. Nếu bộ nhớ trong buffer là không đủ để đáp ứng cho toàn bộ chuỗi, nó sẽ ghi một phần của chuỗi đó.

Ví dụ minh họa cách ghi dữ liệu vào Buffer trong Node.js

Ở ví dụ này, mình sử dụng phương thức write() nhận tham số là dữ liệu dạng chuỗi để ghi dữ liệu đó tới Buffer.

buf = new Buffer(256);
len = buf.write("Hoc Nodejs tai VietJack");

console.log("Tong so byte da ghi : "+  len);

Khi chương trình trên được thực thi sẽ cho kết quả:

Tong so byte da ghi : 22

C. Đọc dữ liệu từ Buffer trong Node.js

Cú pháp

Cú pháp để đọc dữ liệu từ Buffer trong Node.js như sau:

buf.toString([encoding][, start][, end])

Chi tiết về tham số

  • encoding - Là mã hóa để sử dụng. Mã hóa mặc định là 'utf8'.

  • start - Chỉ mục để bắt đầu hoạt động đọc, giá trị mặc định là 0.

  • end - Chỉ mục để kết thúc hoạt động đọc, giá trị mặc định là độ dài của Buffer.

Giá trị trả về

Phương thức này giải mã và trả về một chuỗi từ dữ liệu đã được mã hóa trong Buffer bởi sử dụng bộ mã hóa cụ thể.

Ví dụ minh họa cách đọc dữ liệu từ Buffer trong Node.js

buf = new Buffer(26);
for (var i = 0 ; i < 26 ; i++) {
  buf[i] = i + 97;
}

console.log( buf.toString('ascii'));       // Ket qua: abcdefghijklmnopqrstuvwxyz
console.log( buf.toString('ascii',0,5));   // Ket qua: abcde
console.log( buf.toString('utf8',0,5));    // Ket qua: abcde
console.log( buf.toString(undefined,0,5)); // Su dung ma hoa mac dinh 'utf8', Ket qua la: abcde

Khi chương trình trên được thực thi sẽ cho kết quả:

abcdefghijklmnopqrstuvwxyz
abcde
abcde
abcde

D. Chuyển đổi Buffer thành JSON trong Node.js

Cú pháp

Để chuyển đổi một Buffer trong Node.js thành đối tượng JSON, bạn sử dụng phương thức toJSON() có cú pháp nhu sau:

buf.toJSON()

Giá trị trả về

Phương thức này trả về một biểu diễn JSON cho đối tượng Buffer đã cho.

Ví dụ minh họa cách chuyển đổi Buffer thành JSON

var buf = new Buffer('Simply Easy Learning');
var json = buf.toJSON(buf);

console.log(json);

Khi chương trình trên được thực thi sẽ cho kết quả:

[ 83, 105, 109, 112, 108, 121, 32, 69, 97, 115, 121, 32, 76, 101, 97, 114, 110, 105, 110, 103 ]

E.Ghép nối các Buffer trong Node.js

Cú pháp

Để nối ghép hai hoặc nhiều Buffer thành một Buffer trong Node.js, bạn sử dụng phương thức concat() như sau:

Buffer.concat(list[, totalLength])

Chi tiết về tham số

  • list - Xác định một mảng các Buffer được sử dụng để ghép nối thành một Buffer.

  • totalLength - Là tổng độ dài của các Buffer sau khi đã được ghép nối.

Giá trị trả về

Phương thức này trả về một Buffer mới.

Ví dụ minh họa cách ghép nối các Buffer

var buffer1 = new Buffer('titoe cung cap loat bai huong dan mien phi ');
var buffer2 = new Buffer('cho tat ca moi nguoi');
var buffer3 = Buffer.concat([buffer1,buffer2]);
console.log("Noi dung cua buffer3 la: " + buffer3.toString());

Khi chương trình trên được thực thi sẽ cho kết quả:

Noi dung cua buffer3 la: titoe cung cap loat bai huong dan mien phi cho tat ca moi nguoi

F. So sánh các Buffer trong Node.js

Cú pháp

Để so sánh hai Buffer trong Node.js, bạn sử dụng phương thức compare() như sau:

buf.compare(otherBuffer);

Chi tiết về tham số

  • otherBuffer - Một Buffer khác để được so sánh với Buffer có tên là buf.

Giá trị trả về

Trả về một giá trị dạng số thể hiện Buffer này là đứng trước, sau hay cùng thứ tự với Buffer kia.

Ví dụ minh họa cách so sánh hai Buffer trong Node.js

var buffer1 = new Buffer('ABC');
var buffer2 = new Buffer('ABCD');
var result = buffer1.compare(buffer2);

if(result < 0) {
   console.log(buffer1 +" dung truoc " + buffer2);
}else if(result == 0){
   console.log(buffer1 +" cung thu tu voi " + buffer2);
}else {
   console.log(buffer1 +" dung sau " + buffer2);
}

Khi chương trình trên được thực thi sẽ cho kết quả:

ABC dung truoc ABCD

G. Sao chép Buffer trong Node.js

Cú pháp

Để sao chép Buffer trong Node.js, bạn sử dụng phương thức copy() như sau:

buf.copy(targetBuffer[, targetStart][, sourceStart][, sourceEnd])

Chi tiết về tham số

  • targetBuffer - Đối tượng Buffer, đây là nơi Buffer sẽ được sao chép.

  • targetStart - Dạng số, mặc định là 0.

  • sourceStart - Dạng số, mặc định là 0.

  • sourceEnd - Dạng số, mặc định là độ dài của buffer.

Giá trị trả về

Phương thức copy() này không trả về bất kỳ giá trị nào.

Ví dụ minh họa cách sao chép Buffer

var buffer1 = new Buffer('ABC');
// Sao chep mot buffer
var buffer2 = new Buffer(3);
buffer1.copy(buffer2);
console.log("Noi dung cua buffer2 la: " + buffer2.toString());

Khi chương trình trên được thực thi sẽ cho kết quả:

Noi dung cua buffer2 la: ABC

H. Chia nhỏ Buffer trong Node.js

Cú pháp

Để lập một Buffer con của một Buffer trong Node.js, bạn sử dụng phương thức slice() như sau:

buf.slice([start][, end])

Chi tiết về tham số

  • start - Dạng số, giá trị mặc định là 0.

  • end - Dạng số, giá trị mặc định là buffer.length

Giá trị trả về

Trả về một Buffer mới mà tham chiếu tới cùng vùng bộ nhớ như Buffer cũ.

Ví dụ

var buffer1 = new Buffer('VietNamVoDoi');
//Chia nho mot buffer
var buffer2 = buffer1.slice(0,7);
console.log("Noi dung cua buffer2 la: " + buffer2.toString());

Khi chương trình trên được thực thi sẽ cho kết quả:

Noi dung cua buffer2 la: VietNam

K. Độ dài Buffer trong Node.js

Cú pháp

Để lấy độ dài (bằng giá trị byte) của một Buffer trong Node.js, bạn sử dụng thuộc tính length như sau:

buf.length;

Giá trị trả về

Trả về độ dài bằng byte của một Buffer.

Ví dụ

var buffer = new Buffer('VietNamVoDoi');
//Do dai cua buffer
console.log("Do dai cua buffer la: " + buffer.length);

Khi chương trình trên được thực thi sẽ cho kết quả:

Do dai cua buffer la: 12

11. Stream trong Node.js

A. Stream là gì ?

Stream là các đối tượng cho phép bạn đọc dữ liệu từ một nguồn và ghi dự liệu đến một đích. Trong Node.js, có 4 loại Stream.

  • Readable - Là Stream được sử dụng để cho hoạt động đọc

  • Writable - Là Stream được sử dụng cho hoạt động ghi

  • Duplex - Là Stream được sử dụng cho cả mục đích ghi và đọc

  • Transform - Đây là một kiểu Duplex Stream, khác ở chỗ là kết quả đầu ra được tính toán dựa trên dữ liệu bạn đã nhập vào.

Mỗi loại Stream là một sự thể hiện của đối tượng EventEmitter và ném một vài sự kiện tại các thời điểm khác nhau. Danh sách sau liệt kê một số sự kiện thường được sử dụng:

  • data - Sự kiện này được kích hoạt khi dữ liệu là có sẵn cho hoạt động đọc.

  • end - Sự kiện này được kích hoạt khi không còn dữ liệu nào để đọc nữa.

  • error - Sự kiện này được kích hoạt khi xảy ra bất kỳ lỗi nào trong việc đọc và ghi dữ liệu.

  • finish - Sự kiện này được kích hoạt khi tất cả dữ liệu đã được chuyển hết tới vùng hệ thống cơ sở.

Phần tiếp theo mình sẽ trình bày chi tiết các hoạt động thường sử dụng trên các Stream.

B. Đọc dữ liệu từ Stream trong Node.js

Đầu tiên, bạn tạo một text file với tên input.txt có nội dung sau:

titoe.net la trang Web huong dan cac bai lap trinh
hoan toan mien phi cho tat ca moi nguoi!!!!!

Tạo một js file có tên main.js. Trong file này, đầu tiên bạn khai báo fs Module (đây là Module cho các hoạt động File I/O) bởi sử dụng phương thức require(). Sau đó sử dụng phương thức createReadStream() nhận tham số là tên của text file bạn đã tạo trước đó để đọc dữ liệu từ đó.

var fs = require("fs");
var data = '';

// Tao mot Readable Stream
var readerStream = fs.createReadStream('input.txt');

// Thiet lap encoding la utf8. 
readerStream.setEncoding('UTF8');

// Xu ly cac su kien lien quan toi Stream --> data, end, va error
readerStream.on('data', function(chunk) {
   data += chunk;
});

readerStream.on('end',function(){
   console.log(data);
});

readerStream.on('error', function(err){
   console.log(err.stack);
});

console.log("Ket thuc chuong trinh");

Bây giờ chạy main.js để xem kết quả:

$ node main.js

Kiểm tra kết quả đầu ra:

Ket thuc chuong trinh
titoe.net la trang Web huong dan cac bai lap trinh
hoan toan mien phi cho tat ca moi nguoi!!!!!

C. Ghi dữ liệu tới Stream trong Node.js

Bạn cũng tạo một main.js như trên. Khác ở chỗ là thay vì sử dụng createReadStream(), bạn sử dụng phương thức createWriteStream() nhận tham số là file để chứa kết quả bạn cần ghi:

var fs = require("fs");
var data = 'VietNamVoDoi';

// Tao mot Writable Stream
var writerStream = fs.createWriteStream('output.txt');

// Ghi du lieu toi Stream theo ma hoa utf8
writerStream.write(data,'UTF8');

// Danh dau diem cuoi cua file (end of file)
writerStream.end();

// Xu ly cac su kien lien quan toi Stream --> finish, va error
writerStream.on('finish', function() {
    console.log("Ket thuc hoat dong ghi.");
});

writerStream.on('error', function(err){
   console.log(err.stack);
});

console.log("Ket thuc chuong trinh");

Bây giờ chạy main.js để xem kết quả:

$ node main.js

Kiểm tra kết quả:

Ket thuc chuong trinh
Ket thuc hoat dong ghi.

Bây giờ, bạn mở output.txt đã được tạo trong thư mục hiện tại và kiểm tra nội dung kết quả thu được:

VietNamVoDoi

D. Khái niệm Piping Stream trong Node.js

Piping là một kỹ thuật. Với kỹ thuật này, chúng ta cung cấp kết quả đầu ra của một Stream để làm dữ liệu đầu vào cho một Stream khác. Không có giới hạn nào về hoạt động Piping này, tức là quá trình trên có thể vẫn tiếp tục.

Để hiểu thêm về khái niệm này, bạn theo dõi ví dụ dưới đây. Trong ví dụ này, mình đọc dữ liệu từ một file, sau đó ghi dữ liệu đó tới một file khác.

Đầu tiên, bạn tạo js file có tên main.js chẳng hạn. Trong file này, bạn sử dụng hai phương thức đã trình bày ở trên là createReadStream() và createWriteStream() tương ứng để đọc và ghi dữ liệu. Tiếp đó, sử dụng phương thức pipe() để thực hiện kỹ thuật Piping Stream như sau:

var fs = require("fs");

// Tao mot Readable Stream
var readerStream = fs.createReadStream('input.txt');

// Tao mot Writable Stream
var writerStream = fs.createWriteStream('output.txt');

// Piping hoat dong Readable va Writable
// Doc du lieu tu input.txt va ghi du lieu toi output.txt
readerStream.pipe(writerStream);

console.log("Ket thuc chuong trinh");

Chạy main.js để xem kết quả:

$ node main.js

Kiểm tra kết quả:

Ket thuc chuong trinh

Mở output.txt đã được tạo trong thư mục hiện tại của bạn và kiểm tra nội dung:

titoe.net la trang Web huong dan cac bai lap trinh
hoan toan mien phi cho tat ca moi nguoi!!!!!

E. Khái niệm Chaining Stream trong Node.js

Chaining là một kỹ thuật để kết nối kết quả đầu ra của một Stream tới một Stream khác và tạo một chuỗi bao gồm nhiều hoạt động Stream. Thường thì nó được sử dụng với các hoạt động Piping.

Ví dụ sau minh họa cách kết hợp hai hoạt động Piping và Chaining. Đầu tiên chúng ta nén một file, sau đó giải nén file đó.

Tạo main.js. Trong file này, mình cần khai báo zlip Module cung cấp phương thức createGzip() cho hoạt động nén.

var fs = require("fs");
var zlib = require('zlib');

// Nen input.txt thanh input.txt.gz
fs.createReadStream('input.txt')
  .pipe(zlib.createGzip())
  .pipe(fs.createWriteStream('input.txt.gz'));
  
console.log("File duoc nen thanh cong.");

Chạy main.js để xem kết quả:

$ node main.js

Kiểm tra kết quả:

File duoc nen thanh cong.

Sau khi kiểm tra, bạn sẽ thấy rằng input.txt đã được nén và nó đã tạo một input.txt.gz trong thư mục hiện tại. Bây giờ, bạn thử giải nén cùng file trên bởi sử dụng phương thức createGunzip() của zlib Module như sau:

var fs = require("fs");
var zlib = require('zlib');

// Giai nen input.txt.gz thanh input.txt
fs.createReadStream('input.txt.gz')
  .pipe(zlib.createGunzip())
  .pipe(fs.createWriteStream('input.txt'));
  
console.log("Giai nen File thanh cong.");

Chạy main.js để xem kết quả:

$ node main.js

Kiểm tra kết quả:

Giai nen File thanh cong.

12 . Đọc, ghi file trong Node.js

Trong các chương trước, bạn thấy rằng mình đã sử dụng rất nhiều cú pháp require("fs"). Vậy cú pháp để làm gì ? Đây là cú pháp để khai báo fs Module để triển khai các hoạt động về File I/O trong Node.js. Cú pháp như sau:

var fs = require("fs")

A. Khái niệm Đồng bộ vs Không đồng bộ trong Node.js

Mỗi phương thức trong fs Module có các form đồng bộ và các form không đồng bộ. Các phương thức không đồng bộ nhận một tham số cuối cùng là một hàm callback thực thi khi kết thúc và nhận tham số đầu tiên là một hàm callback để xử lý lỗi. Việc sử dụng các phương thức không đồng bộ là tốt hơn các phương thức đồng bộ, bởi vì các phương thức không đồng bộ không bao giờ khóa trình thực thi chương trình trong khi phương thức đồng bộ thì có.

Ví dụ

Để minh họa hoạt động I/O trong Node.js, đầu tiên bạn tạo input.txt có nội dung:

titoe.net la trang Web huong dan cac bai lap trinh
hoan toan mien phi cho tat ca moi nguoi!!!!!

Tạo main.js. Như trên đã trình bày, mỗi phương thức của fs Module đều có hai form là đồng bộ và không đồng bộ. Để đọc dữ liệu, mình sử dụng phương thức readFile() của form không đồng bộ và readFileSync() của form đồng bộ để đọc dữ liệu. Hai phương thức này nhận tham số đầu tiên là tên file để đọc dữ liệu từ đó.

var fs = require("fs");

// Phuong thuc doc file khong dong bo
fs.readFile('input.txt', function (err, data) {
   if (err) {
       return console.error(err);
   }
   console.log("Phuong thuc doc file khong dong bo: " + data.toString());
});

// Phuong thuc doc file dong bo
var data = fs.readFileSync('input.txt');
console.log("Phuong thuc doc file dong bo: " + data.toString());

console.log("Ket thuc chuong trinh");

Chạy main.js để xem kết quả:

$ node main.js

Kiểm tra kết quả:

Phuong thuc doc file dong bo: titoe.net la trang Web huong dan cac bai lap trinh
hoan toan mien phi cho tat ca moi nguoi!!!!!

Ket thuc chuong trinh
Phuong thuc doc file khong dong bo: titoe.net la trang Web huong dan cac bai lap trinh
hoan toan mien phi cho tat ca moi nguoi!!!!!

Phần tiếp theo mình sẽ trình bày chi tiết các hoạt động về File I/O thường gặp:

B. Mở một File trong Node.js

Cú pháp

Để mở một file trong chế độ không đồng bộ, bạn sử dụng phương thức open() có cú pháp:

fs.open(path, flags[, mode], callback)

Tham số

  • path - Đây là một chuỗi biểu diễn tên file cũng như đường dẫn tới file đó.

  • flags - Biểu diễn hành vi của file được mở. Tất cả các giá trị có thể sẽ được trình bày trong bảng dưới đây.

  • mode - Thiết lập chế độ cho file, các chế độ này chỉ được thiết lập khi file đã được tạo. Giá trị mặc định là 0666, tức là readable và writeable.

  • callback - Hàm callback nhận hai tham số, ví dụ (err, fd).

Các Flag được sử dụng cho hoạt động Đọc/Ghi file trong Node.js

Flag Miêu tả
r Mở file để đọc. Xuất hiện Exception nếu file không tồn tại.
r+ Mở file để đọc và ghi. Xuất hiện Exception nếu file không tồn tại.
rs Mở file để đọc trong chế độ đồng bộ.
rs+ Mở file để đọc và ghi, báo cho Hệ điều hành mở nó trong chế độ đồng bộ.
w Mở file để ghi. Nếu file không tồn tại, nó sẽ tạo file mới.
wx Giống 'w' nhưng hoạt động này thất bại nếu file không tồn tại (tức là nó không tạo file mới).
w+ Mở file để đọc và ghi. Nếu file không tồn tại, nó sẽ tạo file mới.
wx+ Giống 'w+' nhưng hoạt động này thất bại nếu file không tồn tại
a Mở file để append. File sẽ được tạo nếu nó không tồn tại.
ax Giống 'a' nhưng hoạt động này thất bại nếu file không tồn tại.
a+ Mở file để đọc và append. File sẽ được tạo nếu nó không tồn tại.
ax+ Giống 'a+' nhưng hoạt động này thất bại nếu file không tồn tại.

Ví dụ

Ví dụ sau minh họa cách mở một file để đọc và ghi. Đầu tiên bạn tạo main.js có nội dung như dưới đây. Nội dung file khá giống ví dụ trên, bạn chú ý vào phần flag đã sử dụng ở đây.

var fs = require("fs");

// Hoat dong mo File theo cach thuc khong dong bo
console.log("Chuan bi mo File hien tai!");
fs.open('input.txt', 'r+', function(err, fd) {
   if (err) {
       return console.error(err);
   }
  console.log("File duoc mo thanh cong!");     
});

Chạy main.js để xem kết quả:

$ node main.js

Kiểm tra kết quả:

Chuan bi mo File hien tai!
File duoc mo thanh cong!

C. Lấy thông tin File trong Node.js

Cú pháp

Để lấy thông tin về một file trong Node.js, bạn sử dụng phương thức stat() của fs Module có cú pháp:

fs.stat(path, callback)

Chi tiết về tham số

  • path - Đây là một chuỗi biểu diễn tên file cũng như đường dẫn tới file đó.

  • callback - Là hàm callback nhận hai tham số (err, stats), trong đó stats là một đối tượng của fs.Stats được in ra như trong ví dụ sau.

Ngoài các thuộc tính quan trọng được in ra như trong ví dụ sau, lớp fs.Stats còn có một số phương thức hữu ích có thể được sử dụng để kiểm tra kiểu file. Đó là:

Phương thức Miêu tả
stats.isFile() Trả về true nếu đó là một file
stats.isDirectory() Trả về true nếu đó là một thư mục
stats.isBlockDevice() Trả về true nếu đó là một Block Device.
stats.isCharacterDevice() Trả về true nếu đó là một Character Device.
stats.isSymbolicLink() Trả về true nếu đó là một Symbolic Link.
stats.isFIFO() Trả về true nếu đó là một kiểu FIFO.
stats.isSocket() Trả về true nếu đó là một kiểu Socket.

Ví dụ

Sau đây là ví dụ minh họa cách lấy thông tin về một file nào đó. Tạo main.js và sử dụng phương thức stat() của fs Module đã trình bày ở trên:

var fs = require("fs");

console.log("Chuan bi lay thong tin File hien tai!");
fs.stat('input.txt', function (err, stats) {
   if (err) {
       return console.error(err);
   }
   console.log(stats);
   console.log("Lay thong tin File thanh cong!");
   
   // Kiem tra kieu file
   console.log("isFile ? " + stats.isFile());
   console.log("isDirectory ? " + stats.isDirectory());    
});

Chạy main.js để xem kết quả:

$ node main.js

Kiểm tra kết quả:

Chuan bi lay thong tin File hien tai!
{ dev: 1792,
  mode: 33188,
  nlink: 1,
  uid: 48,
  gid: 48,
  rdev: 0,
  blksize: 4096,
  ino: 4318127,
  size: 97,
  blocks: 8,
  atime: Sun Mar 22 2015 13:40:00 GMT-0500 (CDT),
  mtime: Sun Mar 22 2015 13:40:57 GMT-0500 (CDT),
  ctime: Sun Mar 22 2015 13:40:57 GMT-0500 (CDT) }
Lay thong tin File thanh cong!
isFile ? true
isDirectory ? false

D. Ghi dữ liệu vào File trong Node.js

Cú pháp

Để ghi dữ liệu vào File trong Node.js, bạn có thể sử dụng phương thức writeFile() của fs Module như sau:

fs.writeFile(filename, data[, options], callback)

Phương thức này sẽ ghi đè nếu file đã tồn tại.

Chi tiết về tham số

  • path - Đây là một chuỗi biểu diễn tên file cũng như đường dẫn tới file đó.

  • data - Dữ liệu dạng String hoặc Buffer để ghi vào File.

  • options - Tham số này là một đối tượng giữ {encoding, mode, flag}. Theo mặc định, mã hóa là utf8, mode là giá trị 0666 và flag là 'w'

  • callback - Hàm callback nhận một tham số là err và được sử dụng để trả về một lỗi nếu xảy ra bất kỳ lỗi nào trong hoạt động ghi

Ví dụ

Ví dụ sau minh họa cách ghi dữ liệu tới một file. Tạo main.js có nội dung như sau:

var fs = require("fs");

console.log("Chuan bi ghi du lieu vao file hien tai");
fs.writeFile('input.txt', 'Hoc Node.js co ban tai titoe.net!',  function(err) {
   if (err) {
       return console.error(err);
   }
   console.log("Ghi du lieu vao file thanh cong!");
   console.log("Doc du lieu vua duoc ghi");
   fs.readFile('input.txt', function (err, data) {
      if (err) {
         return console.error(err);
      }
      console.log("Phuong thuc doc file khong dong bo: " + data.toString());
   });
});

Chạy main.js để xem kết quả:

$ node main.js

Kiểm tra kết quả:

Chuan bi ghi du lieu vao file hien tai
Ghi du lieu vao file thanh cong!
Doc du lieu vua duoc ghi
Phuong thuc doc file khong dong bo: Hoc Node.js co ban tai titoe.net!

E. Đọc dữ liệu từ File trong Node.js

Cú pháp

Để đọc dữ liệu từ một File, bạn sử dụng phương thức read() có cú pháp sau:

fs.read(fd, buffer, offset, length, position, callback)

Phương thức này sẽ sử dụng tham số fd (viết tắt của File Descriptor) để đọc file. Nếu bạn muốn đọc file bởi sử dụng trực tiếp tên file thì bạn nên sử dụng phương thức khác.

Chi tiết về tham số

  • fd - Là viết tắt của file descriptor được trả về bởi phương thức fs.open().

  • buffer - Đây là Buffer, là nơi dữ liệu được ghi vào.

  • offset - Đây là offset trong Buffer để dữ liệu bắt đầu ghi từ vị trí đó.

  • length - Một số nguyên xác định số byte để đọc.

  • position - Một số nguyên xác định nơi bắt đầu đọc từ trong file. Nếu vị trí là null, dữ liệu sẽ được đọc từ vị trí hiện tại của file.

  • callback - Một hàm callback nhận ba tham số, có dạng (err, bytesRead, buffer).

Ví dụ

Tạo main.js có nội dung sau:

var fs = require("fs");
var buf = new Buffer(1024);

console.log("Chuan bi mo mot File dang ton tai");
fs.open('input.txt', 'r+', function(err, fd) {
   if (err) {
       return console.error(err);
   }
   console.log("File duoc mo thanh cong!");
   console.log("Chuan bi doc du lieu tu File da mo");
   fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
      if (err){
         console.log(err);
      }
      console.log(bytes + " bytes read");
      
      // In so luong byte da doc.
      if(bytes > 0){
         console.log(buf.slice(0, bytes).toString());
      }
   });
});

Chạy main.js để xem kết quả:

$ node main.js

Kiểm tra kết quả:

Chuan bi mo mot File dang ton tai
File duoc mo thanh cong!
Chuan bi doc du lieu tu File da mo
97 bytes read
titoe.net la trang Web huong dan cac bai lap trinh
hoan toan mien phi cho tat ca moi nguoi!!!!!

F. Đóng File trong Node.js

Cú pháp

Để đóng một file sau khi đã mở, bạn sử dụng phương thức close() có cú pháp:

fs.close(fd, callback)

Chi tiết về tham số

  • fd - Là viết tắt của file descriptor được trả về bởi phương thức fs.open().

  • callback - Hàm callback nhận một tham số để xử lý trường hợp nếu có exception.

Ví dụ

Tạo main.js có nội dung:

var fs = require("fs");
var buf = new Buffer(1024);

console.log("Chuan bi mo mot File dang ton tai");
fs.open('input.txt', 'r+', function(err, fd) {
   if (err) {
       return console.error(err);
   }
   console.log("File duoc mo thanh cong!");
   console.log("Chuan bi doc du lieu tu File da mo");
   fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
      if (err){
         console.log(err);
      }

      // In so luong byte da doc.
      if(bytes > 0){
         console.log(buf.slice(0, bytes).toString());
      }

      // Dong mot File vua duoc mo.
      fs.close(fd, function(err){
         if (err){
            console.log(err);
         } 
         console.log("File duoc dong thanh cong.");
      });
   });
});

Chạy main.js để xem kết quả:

$ node main.js

Kiểm tra kết quả:

Chuan bi mo mot File dang ton tai
File duoc mo thanh cong!
Chuan bi doc du lieu tu File da mo
titoe.net la trang Web huong dan cac bai lap trinh
hoan toan mien phi cho tat ca moi nguoi!!!!!

File duoc dong thanh cong.

G. Truncate một File trong Node.js

Cú pháp

Để truncate một file đã mở, bạn sử dụng phương thúc ftruncate() có cú pháp:

fs.ftruncate(fd, len, callback)

Chi tiết về tham số

  • fd - Là viết tắt của file descriptor được trả về bởi phương thức fs.open().

  • len - Là độ dài của file sau khi đã được truncate.

  • callback - Hàm callback nhận một tham số để xử lý trường hợp nếu có exception.

Ví dụ

Tạo main.js có nội dung sau:

var fs = require("fs");
var buf = new Buffer(1024);

console.log("Chuan bi mo mot File dang ton tai");
fs.open('input.txt', 'r+', function(err, fd) {
   if (err) {
       return console.error(err);
   }
   console.log("File duoc mo thanh cong!");
   console.log("Chuan bi truncate file");
   
   // Truncate mot File da duoc mo.
   fs.ftruncate(fd, 10, function(err){
      if (err){
         console.log(err);
      } 
      console.log("File duoc truncate thanh cong.");
      console.log("Chuan bi doc du lieu tu File"); 
      fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
         if (err){
            console.log(err);
         }

         // In so luong byte da doc.
         if(bytes > 0){
            console.log(buf.slice(0, bytes).toString());
         }

         // Dong File vua mo.
         fs.close(fd, function(err){
            if (err){
               console.log(err);
            } 
            console.log("File duoc dong thanh cong.");
         });
      });
   });
});

Chạy main.js để xem kết quả:

$ node main.js

Kiểm tra kết quả:

Chuan bi mo mot File dang ton tai
File duoc mo thanh cong!
Chuan bi truncate file
File duoc truncate thanh cong.
Chuan bi doc du lieu tu File
VietNamVo 
File duoc dong thanh cong.

H. Xóa File trong Node.js

Cú pháp

Để xóa một file trong Node.js, bạn sử dụng phương thức unlink() có cú pháp:

fs.unlink(path, callback)

Chi tiết về tham số

  • path - Là tên file hoặc tên đường dẫn trỏ đến file.

  • callback - Hàm callback nhận một tham số để xử lý trường hợp nếu có exception.

Ví dụ

Tạo main.js có nội dung sau:

var fs = require("fs");

console.log("Chuan bi xoa mot File dang ton tai");
fs.unlink('input.txt', function(err) {
   if (err) {
       return console.error(err);
   }
   console.log("Xoa File thanh cong!");
});

Chạy main.js để xem kết quả:

$ node main.js

Kiểm tra kết quả:

Chuan bi xoa mot File dang ton tai
Xoa File thanh cong!

K. Tạo thư mục trong Node.js

Cú pháp

Để tạo một thư mục trong Node.js, bạn sử dụng phương thức mkdir() có cú pháp:

fs.mkdir(path[, mode], callback)

Chi tiết về tham số

  • path - Là tên thư mục bao gồm đường dẫn trỏ tới thư mục đó.

  • mode - Chế độ xác định các quyền cho phép khi truy cập thư mục. Giá trị mặc định là 0777.

  • callback - Hàm callback nhận một tham số để xử lý trường hợp nếu có exception.

Ví dụ

Tạo main.js có nội dung sau:

var fs = require("fs");

console.log("Chuan bi tao thu muc /tmp/test");
fs.mkdir('/tmp/test',function(err){
   if (err) {
       return console.error(err);
   }
   console.log("Thu muc duoc tao thanh cong!");
});

Chạy main.js để xem kết quả:

$ node main.js

Kiểm tra kết quả:

Chuan bi tao thu muc /tmp/test
Thu muc duoc tao thanh cong!

T. Đọc thư mục trong Node.js

Cú pháp

Để đọc thư mục trong Node.js, bạn sử dụng phương thức readdir() có cú pháp:

fs.readdir(path, callback)

Chi tiết về tham số

  • path - Là tên thư mục bao gồm đường dẫn trỏ tới thư mục đó.

  • callback - Hàm callback nhận hai tham số, dạng (err, files) trong đó files là một mảng chứa các tên file trong thư mục.

Ví dụ

Tạo main.js có nội dung sau:

var fs = require("fs");

console.log("Chuan bi doc thon tin tu thu muc /tmp");
fs.readdir("/tmp/",function(err, files){
   if (err) {
       return console.error(err);
   }
   files.forEach( function (file){
       console.log( file );
   });
});

Chạy main.js để xem kết quả:

$ node main.js

Kiểm tra kết quả:

Chuan bi doc thon tin tu thu muc /tmp
ccmzx99o.out
ccyCSbkF.out
employee.ser
hsperfdata_apache
test
test.txt

M. Xóa thư mục trong Node.js

Cú pháp

Để xóa một thư mục trong Node.js, bạn sử dụng phương thức rmdir() có cú pháp:

fs.rmdir(path, callback)

Chi tiết về tham số

  • path - Là tên thư mục bao gồm đường dẫn trỏ tới thư mục đó.

  • callback - Hàm callback nhận một tham số để xử lý trường hợp nếu có exception.

Ví dụ

Tạo main.js có nội dung sau:

var fs = require("fs");

console.log("Chuan bi xoa thu muc /tmp/test");
fs.rmdir("/tmp/test",function(err){
   if (err) {
       return console.error(err);
   }
   console.log("Chuan bi doc thon tin tu thu muc /tmp");
   fs.readdir("/tmp/",function(err, files){
      if (err) {
          return console.error(err);
      }
      files.forEach( function (file){
          console.log( file );
      });
   });
});

Chạy main.js để xem kết quả:

$ node main.js

Kiểm tra kết quả:

Chuan bi doc thon tin tu thu muc /tmp
ccmzx99o.out
ccyCSbkF.out
employee.ser
hsperfdata_apache
test.txt

13. Đối tượng toàn cục trong Node.js

Khái niệm Toàn cục (Global) tức là mọi thứ đều có quyền truy cập đến. Trong Node.js cũng vậy, các đối tượng toàn cục là có sẵn cho tất cả Module. Chúng ta không cần khai báo hay import chúng bởi phương thức require() mà vẫn có thể sử dụng chúng một cách trực tiếp. Các đối tượng này có thể là các Module, các hàm, các chuỗi hoặc các đối tượng.

__filename trong Node.js

Trong Node.js, __filename biểu diễn tên file của đoạn code đang được thực thi. Đây là đường dẫn tuyệt đối tới file chứa phần code này.

Ví dụ

Để minh họa cho _filenam trong Node.js, bạn tạo main.js có nội dung đơn giản sau:

// In gia tri cua __filename trong Node.js

console.log( __filename );

Chạy main.js để xem kết quả:

$ node main.js

Kết quả in ra chính là đường dẫn tới main.js chứa đoạn code trên:

/web/com/1427091028_21099/main.js

__dirname trong Node.js

Trong Node.js, __dirname biểu diễn thư mục chứa đoạn code mà đang được thực thi.

Ví dụ

Để minh họa cho việc lấy thông tin của _dirname trong Node.js, bạn tạo main.js chứa đoạn code đơn giản sau:

// In gia tri cua __dirname trong Node.js

console.log( __dirname );

Chạy main.js để xem kết quả::

$ node main.js

Kết quả in ra là thư mục hiện tại chứa main.js:

/web/com/1427091028_21099

A. Hàm setTimeout(cb, ms) trong Node.js

Hàm toàn cục setTimeout(cb, ms) được sử dụng để chạy hàm callback có tên là cb sau một khoảng thời gian ms milisecond.

Hàm toàn cục này trả về một giá trị biểu diễn Timer để có thể được xóa bởi hàm clearTimeout().

Ví dụ

Để minh họa cách sử dụng của hàm setTimeout() trong Node.js, bạn tạo main.js có nội dung như sau:

function printHello(){
   console.log( "Hello World!");
}
// Bay gio goi ham printHello sau 2 giay
setTimeout(printHello, 2000);

Chạy main.js để xem kết quả::

$ node main.js

Kết quả sẽ hiện ra sau khoảng 2s. Khoảng thời gian này có thể lâu hơn 2s bởi vì thời gian delay còn bị ảnh hưởng bởi các yếu tố bên ngoài như OS Timer:

Hello World!

B. Hàm clearTimeout(t) trong Node.js

Hàm toàn cục clearTimeout( t ) được sử dụng để dừng một Timer đã được tạo bởi hàm setTimeout() trước đó. Tham số t chính là Timer được trả về từ hàm setTimeout().

Ví dụ

Để xóa Timer đã được thiết lập trước đó, bạn tạo main.js có nội dung đơn giản như sau. Trước tiên, chúng ta thiết lập Timer bởi hàm setTimeout(), sau đó sử dụng hàm clearTimeout() để xóa giá trị này:

function printHello(){
   console.log( "Hello World!");
}
// Bay gio goi ham printHello sau 2 giay
var t = setTimeout(printHello, 2000);

// Bay gio xoa Timer da duoc thiet lap o tren
clearTimeout(t);

Chạy main.js để xem kết quả::

$ node main.js

Trên terminal sẽ không hiển thị kết quả gì.

C. Hàm setInterval(cb, ms) trong Node.js

Hàm toàn cục setInterval(cb, ms) được sử dụng để chạy hàm callback có tên là cb một cách lặp đi lặp lại sau một khoảng thời gian ms millisecond.

Hàm toàn cục này trả về một giá trị biểu diễn Timer để có thể được xóa bởi hàm clearInterval(t).

Ví dụ

Để thấy cách sử dụng của hàm setInterval() trong Node.js, bạn tạo main.js có nội dung đơn giản sau:

function printHello(){
   console.log( "Hello World!");
}
// Bay gio, chung ta goi ham pringtHello sau 2 giay
setInterval(printHello, 2000);

Chạy main.js để xem kết quả::

$ node main.js

Chương trình trên sẽ thực thi hàm printHello() sau mỗi 2 s.

D. Một số đối tượng toàn cục trong Node.js

Ngoài các thuộc tính và hàm toàn cục trên, Node.js còn bao gồm một số đối tượng toàn cục khác. Bạn theo link sau để tìm hiểu chi tiết:

Stt Đối tượng & Miêu tả
1 Đối tượng Console
Được sử dụng để in thông tin trên stdout và stderr.
2 Đối tượng Process
Được sử dụng để lấy thông tin về tiến trình hiện tại.

 

14. Utility Module trong Node.js

Thư viện Node.js Module cung cấp nhiều Utility Module giúp ích bạn rất nhiều trong khi phát triển các ứng dụng về Node.js. Bảng dưới đây liệt kê và miêu tả các Utility Module này.

Stt Tên Module & Miêu tả
1 os Module
Cung cấp các hàm tiện ích cơ bản liên quan tới hệ điều hành.
2 path Module
Cung cấp các tiện ích để xử lý và biến đổi đường dẫn tới file.
3 net Module
Hoạt động như là Network Wrapper, biến Server và Client thành các Stream.
4 dns Module
Cung cấp các hàm để thực hiện DNS Lookup.
5 domain Module
Được sử dụng để can thiệp các lỗi chưa được xử lý

 

15. Web Module trong Node.js

A. Web Server là gì ?

Web Server là một ứng dụng phần mềm có thể xử lý các HTTP request được gửi bởi HTTP Client (ví dụ: trình duyệt web) và trả về một trang web trong phản hồi tới Client. Web Server thường gửi các tài liệu html bên cạnh các ảnh cũng như style sheet và các đoạn Javascript.

B. Cấu trúc ứng dụng Web

Một ứng dụng web thường được chia thành 4 lớp như sau:

Cấu trúc ứng dụng Web

  • Client - Lớp này bao gồm các trình duyệt web và các ứng dụng có thể tạo ra các HTTP request đến Web Server.

  • Server - Lớp này bao gồm các Web Server có thể can thiệp các request được tạo bởi Client và trả về các phản hồi (response).

  • Business - Lớp này bao gồm ứng dụng trên Server có thể được tận dụng bởi các Web Server để thực hiện các tiến trình xử lý cần thiết. Lớp này tương tác với lớp Data qua các chương trình bên ngoài.

  • Data - Lớp này bao gồm các Database và bất kì các nguồn dữ liệu nào.

C. Tạo Web Server bởi sử dụng Node.js

Node.js cung cấp http Module có thể được sử dụng để tạo các HTTP client và server. Dưới đây là phần kiến trúc thu nhỏ của HTTP Server được lắng nghe trên cổng 8081.

Đầu tiên, bạn tạo server.js có nội dung như sau:

var http = require('http');
var fs = require('fs');
var url = require('url');


// Tao mot Server
http.createServer( function (request, response) {  
   // Parse request co chua ten file
   var pathname = url.parse(request.url).pathname;
   
   // In thong tin ve ten file ma tu do Request duoc tao.
   console.log("Request cho " + pathname + " da duoc nhan.");
   
   // Doc noi dung tu File da duoc yeu cau boi Request
   fs.readFile(pathname.substr(1), function (err, data) {
      if (err) {
         console.log(err);
         // HTTP Status: 404 : NOT FOUND
         // Content Type: text/plain
         response.writeHead(404, {'Content-Type': 'text/html'});
      }else{	
         // HTTP Status: 200 : OK
         // Content Type: text/plain
         response.writeHead(200, {'Content-Type': 'text/html'});	
         
         // Ghi noi dung cua File toi phan BODY cua Response
         response.write(data.toString());		
      }
      // Gui phan BODY cua Response 
      response.end();
   });   
}).listen(8081);

// In thong bao sau tren console
console.log('Server dang chay tai dia chi: http://127.0.0.1:8081/');

Bây giờ tạo index.htm cùng thư mục với server.js:

<html>
<head>
<title>Vi du Web Module trong Node.js</title>
</head>
<body>
Hello World!
</body>
</html>

Chạy server.js để xem kết quả:

$ node server.js

Kiểm tra kết quả

Server dang chay tai dia chi: http://127.0.0.1:8081/

D. Tạo Request tới Node.js Server

Mở http://127.0.0.1:8081/index.htm trong bất kỳ trình duyệt nào và xem kết quả.

Ứng dụng Node.js

Kiểm tra kết quả:

Server dang chay tai dia chi: http://127.0.0.1:8081/
Request cho /index.htm da duoc nhan.

E. Tạo Web Client bởi sử dụng Node.js

Để tạo Web Client, bạn cũng có thể sử dụng http Module. Dưới đây là ví dụ minh họa.

Tạo client.js có nội dung sau:

var http = require('http');

// Tao doi tuong options duoc su dung boi Request 
var options = {
   host: 'localhost',
   port: '8081',
   path: '/index.htm'  
};

// Ham callback duoc su dung de xu ly Response
var callback = function(response){
   // Tiep tuc cap nhat du lieu toi Stream
   var body = '';
   response.on('data', function(data) {
      body += data;
   });
   
   response.on('end', function() {
      // Ket thuc qua trinh nhan du lieu.
      console.log(body);
   });
}
// Tao mot Request toi Server
var req = http.request(options, callback);
req.end();

Chạy client.js trên một màn hình Terminal khác để xem kết quả:

$ node client.js

Kiểm tra kết quả:

<html>
<head>
<title>Vi du Web Module trong Node.js</title>
</head>
<body>
Hello World!
</body>
</html>

Tiếp đó kiểm tra kết quả trên Server.

Server dang chay tai dia chi: http://127.0.0.1:8081/
Request cho /index.htm da duoc nhan.

16. Express Framework trong Node.js

A. Giới thiệu Express Framework

Express là một framework nhỏ và tiện ích để xây dựng các ứng dụng web, cung cấp một lượng lớn của tính năng mạnh mẽ để phát triển các ứng dụng web và mobile. Nó rất dễ dàng để phát triển các ứng dụng nhanh dựa trên Node.js cho các ứng dụng Web. Dưới đây là các tính năng cơ bản của Express framework.

  • Cho phép thiết lập các lớp trung gian để trả về các HTTP request.

  • Định nghĩ bảng routing có thể được sử dụng với các hành động khác nhau dựa trên phương thức HTTP và URL.

  • Cho phép trả về các trang HTML dựa vào các tham số truyền vào đến template.

B. Cài đặt Express Framework

Đầu tiên, cài đặt Express framework sử dụng npm như sau:

$ npm install express --save

Lệnh trên lưu phần cài đặt trong thư mục node_modules và tạo thư mục express bên trong thư mục đó. Dưới đây là các thành phần module quan trọng được cài đặt cùng với express:

  • body-parser - Đây là một lớp trung gian node.js để xử lí JSON, dự liệu thô, text và mã hóa URL.

  • cookie-parser - Chuyển đổi header của Cookie và phân bố đến các req.cookies

  • multer - Đây là một thành phần trung gian trong node.js để xử lí phần multipart/form-data.

$ npm install body-parser --save
$ npm install cookie-parser --save
$ npm install multer --save

C. Ví dụ ứng dụng Helloworld trong Node.js

Dưới đây là một ví dụ rất cơ bản của Express minh họa cách bật Server và lắng nghe các kết nối trên cổng 3000. Ứng dụng này trả về Hello World! cho các requests đến trang chủ. Đối với các đường dẫn khác, nó sẽ trả về một 404 Not Found.

Tạo server.js có nội dung sau:

var express = require('express');
var app = express();

app.get('/', function (req, res) {
   res.send('Hello World');
})

var server = app.listen(8081, function () {

  var host = server.address().address
  var port = server.address().port

  console.log("Ung dung Node.js dang lang nghe tai dia chi: http://%s:%s", host, port)

})

Chạy server.js để xem kết quả.

$ node server.js

Bạn sẽ thấy kết quả hiện ra:

Ung dung Node.js dang lang nghe tai dia chi: http://0.0.0.0:8081

Mở http://127.0.0.1:8081/ trong bất kỳ trình duyệt nào và xem kết quả.

Ví dụng ứng dụng Express trong Node.js

D. Đối tượng Request & Response trong Node.js

Ứng dụng Express sử dụng một hàm callback có các tham số là các đối tượng request và response.

app.get('/', function (req, res) {
   // --
})

Bạn có thể tham khảo chi tiết về 2 đối tượng này dưới đây:

  • Đối tượng Request - Đối tượng này biểu diễn một HTTP request và có các thuộc tính cho các request như các chuỗi truy vấn, tham số, body, HTTP header và những phần khác.

  • Đối tượng Response - Đối tượng này biểu diễn HTTP response được ứng dụng Express gửi đi khi nó nhận về một HTTP request.

Bạn có thể in ra các đối tượng req và res để cung cấp một lượng lớn thông tin liên quan đến HTTP request và trả về các cookie, session, URL …

E. Định tuyến cơ bản

Ở trên, bạn vừa theo dõi một ứng dụng cơ bản mà Server HTTP request đến một trang chủ. Định tuyến liên quan đến cách xác định một ứng dụng trả về cho một Client Request đến một Endpoint cụ thể, đó là một đường dẫn URI và trả về một phương thức HTTP request (GET, POST và các phương thức khác).

Dựa vào chương trình Hello World trên, mình sẽ phát triển thêm một số chức năng bổ sung để xử lý các HTTP request.

var express = require('express');
var app = express();

// Phuong thuc get() phan hoi mot GET Request ve Homepage
app.get('/', function (req, res) {
   console.log("Nhan mot GET Request ve Homepage");
   res.send('Hello GET');
})


// Phuong thuc post() phan hoi mot POST Request ve Homepage
app.post('/', function (req, res) {
   console.log("Nhan mot POST Request ve Homepage");
   res.send('Hello POST');
})

// Phuong thuc delete() phan hoi mot DELETE Request ve /del_user page.
app.delete('/del_user', function (req, res) {
   console.log("Nhan mot DELETE Request ve /del_user");
   res.send('Hello DELETE');
})

// Phuong thuc nay phan hoi mot GET Request ve /list_user page.
app.get('/list_user', function (req, res) {
   console.log("Nhan mot GET Request ve /list_user");
   res.send('Page Listing');
})

// Phuong thuc nay phan hoi mot GET Request ve abcd, abxcd, ab123cd, ...
app.get('/ab*cd', function(req, res) {   
   console.log("Nhan mot GET request ve /ab*cd");
   res.send('Page Pattern Match');
})


var server = app.listen(8081, function () {

  var host = server.address().address
  var port = server.address().port

  console.log("Ung dung Node.js dang lang nghe tai dia chi: http://%s:%s", host, port)

})

Lưu phần code trong server.js và chạy file này với lệnh sau:

$ node server.js

Kiểm tra kết quả:

Ung dung Node.js dang lang nghe tai dia chi: http://0.0.0.0:8081

Bây giờ, bạn có thể thử các Request khác tại địa chỉ http://127.0.0.1:8081 để xem kết quả tạo bởi server.js. Dưới đây là vài màn hình hiển thị các response khác nhau với các URL khác nhau.

Màn hình kết quả cho http://127.0.0.1:8081/list_user

Ví dụng ứng dụng Express trong Node.js

Màn hình kết quả cho http://127.0.0.1:8081/abcd

Ví dụng ứng dụng Express trong Node.js

Màn hình kết quả cho http://127.0.0.1:8081/abcdefg

Ví dụng ứng dụng Express trong Node.js

F. Đối với các File tĩnh

Express cung cấp các tiện ích lớp trung gian express.static để phục vụ cho các file tĩnh như hình ảnh, CSS, Javascript, ...

Về cơ bản, bạn chỉ cần truyền tên thư mục nơi bạn giữ các file này, express.static sẽ sử dụng file đó một cách trực tiếp. Ví dụ, bạn muốn giữ hình ảnh, CSS và Javascript trong thư mục public, bạn có thể làm như sau:

app.use(express.static('public'));

Giả sử mình giữ một vài hình ảnh trong thư mục con public/images như sau:

node_modules
server.js
public/
public/images
public/images/logo.png

Sửa đổi ứng dụng "Hello Word" trên để thêm một số tính năng bổ sung để xử lý các file tĩnh:

var express = require('express');
var app = express();

app.use(express.static('public'));

app.get('/', function (req, res) {
   res.send('Hello World');
})

var server = app.listen(8081, function () {

  var host = server.address().address
  var port = server.address().port

  console.log("Ung dung Node.js dang lang nghe tai dia chi: http://%s:%s", host, port)

})

Lưu phần code trong server.js và chạy file này với lệnh sau:

$ node server.js

Bây giờ mở trình duyệt và gõ địa chỉ http://127.0.0.1:8081/images/logo.png để xem kết quả.

G. Ví dụ phương thức GET

Dưới đây là một ví dụ đơn giản để truyền 2 giá trị sử dụng HTML FORM với phương thức GET. Mình sẽ sử dụng process_get trong server.js để xử lí phần input.

<html>
<body>
<form action="http://127.0.0.1:8081/process_get" method="GET">
First Name: <input type="text" name="first_name">  <br>

Last Name: <input type="text" name="last_name">
<input type="submit" value="Submit">
</form>
</body>
</html>

Lưu đoạn code trên trong index.htm và sửa đổi server.js như sau.

var express = require('express');
var app = express();

app.use(express.static('public'));

app.get('/index.htm', function (req, res) {
   res.sendFile( __dirname + "/" + "index.htm" );
})

app.get('/process_get', function (req, res) {

   // Chuan bi output trong dinh dang JSON
   response = {
       first_name:req.query.first_name,
       last_name:req.query.last_name
   };
   console.log(response);
   res.end(JSON.stringify(response));
})

var server = app.listen(8081, function () {

  var host = server.address().address
  var port = server.address().port

  console.log("Ung dung Node.js dang lang nghe tai dia chi: http://%s:%s", host, port)

})

Mở trình duyệt và gõ địa chỉ http://127.0.0.1:8081/index.htm để xem kết quả:

 
First Name:
Last Name:

Bây giờ, bạn có thể nhập First Name và Last Name, nhấn nút Submit rồi xem kết quả:

{"first_name":"Hoang","last_name":"Nguyen Manh"}

H. Ví dụ phương thức POST

Dưới đây là ví dụ cơ bản để truyền 2 giá trị sử dụng HTML form bởi sử dụng phương thức POST. Mình sẽ sử dụng process_post trong server.js để xử lí phần input này.

<html>
<body>
<form action="http://127.0.0.1:8081/process_post" method="POST">
First Name: <input type="text" name="first_name">  <br>

Last Name: <input type="text" name="last_name">
<input type="submit" value="Submit">
</form>
</body>
</html>

Lưu đoạn code trên trong index.htm và sửa đổi server.js như sau:

var express = require('express');
var app = express();
var bodyParser = require('body-parser');

// Tao mot parser co dang application/x-www-form-urlencoded
var urlencodedParser = bodyParser.urlencoded({ extended: false })

app.use(express.static('public'));

app.get('/index.htm', function (req, res) {
   res.sendFile( __dirname + "/" + "index.htm" );
})

app.post('/process_post', urlencodedParser, function (req, res) {

   // Chuan bi output trong dinh dang JSON
   response = {
       first_name:req.body.first_name,
       last_name:req.body.last_name
   };
   console.log(response);
   res.end(JSON.stringify(response));
})

var server = app.listen(8081, function () {

  var host = server.address().address
  var port = server.address().port

  console.log("Ung dung Node.js dang lang nghe tai dia chi: http://%s:%s", host, port)

})

Mở trình duyệt và gõ địa chỉ http://127.0.0.1:8081/index.htm để xem kết quả:

 
First Name:
Last Name:

Bây giờ, bạn có thể nhập First Name và Last Name, nhấn nút Submit rồi xem kết quả:

{"first_name":"Hoang","last_name":"Nguyen Manh"}

K. Ví dụ File Upload

Dưới đây là HTML code để tạo một File Upload Form. Form này có những thuộc tính thiết lập đến phương thức POST và thuộc tính mã hóa để thiết lập multipart/form-data.

<html>
<head>
<title>File Uploading Form</title>
</head>
<body>
<h3>File Upload:</h3>
Select a file to upload: <br />
<form action="http://127.0.0.1:8081/file_upload" method="POST" 
      enctype="multipart/form-data">
<input type="file" name="file" size="50" />
<br />
<input type="submit" value="Upload File" />
</form>
</body>
</html>

Lưu đoạn code trên trong index.htm và sửa đổi server.js như sau:

var express = require('express');
var app = express();
var fs = require("fs");

var bodyParser = require('body-parser');
var multer  = require('multer');

app.use(express.static('public'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(multer({ dest: '/tmp/'}));

app.get('/index.htm', function (req, res) {
   res.sendFile( __dirname + "/" + "index.htm" );
})

app.post('/file_upload', function (req, res) {

   console.log(req.files.file.name);
   console.log(req.files.file.path);
   console.log(req.files.file.type);

   var file = __dirname + "/" + req.files.file.name;
   fs.readFile( req.files.file.path, function (err, data) {
        fs.writeFile(file, data, function (err) {
         if( err ){
              console.log( err );
         }else{
               response = {
                   message:'File duoc upload thanh cong!',
                   filename:req.files.file.name
              };
          }
          console.log( response );
          res.end( JSON.stringify( response ) );
       });
   });
})

var server = app.listen(8081, function () {

  var host = server.address().address
  var port = server.address().port

  console.log("Ung dung Node.js dang lang nghe tai dia chi: http://%s:%s", host, port)

})

Bây giờ bạn mở trình duyệt và gõ địa chỉ http://127.0.0.1:8081/index.htm để xem kết quả:

File Upload:
Chọn một File để Upload: 





Ghi chú: Đây chỉ là ví dụ và hiện tại nó sẽ không làm việc.

T. Ví dụ quản lý Cookie

Bạn có thể gửi các Cookie tới Node.js Server. Ví dụ dưới đây minh họa cách in tất cả Cookie được gửi bởi Client.

var express      = require('express')
var cookieParser = require('cookie-parser')

var app = express()
app.use(cookieParser())

app.get('/', function(req, res) {
  console.log("Cookies: ", req.cookies)
})

app.listen(8081)

17. RESTful API trong Node.js

A. Kiến trúc REST là gì ?

REST là viết tắt của Representational State Tranfer. REST là một chuẩn web dựa vào các kiến trúc cơ bản sử dụng giao thức HTTP. Nó xử lí tài nguyên, nơi mà mỗi thành phần là một tài nguyên và nguồn tài nguyên này có thể được truy cập qua các giao diện chung bởi sử dụng các phương thức HTTP chuẩn. REST lần đầu tiên được giới thiệu bởi Roy Fielding năm 2000.

Về cơ bản, một REST Server cung cấp các chế độ truy cập đến nguồn tài nguyên và REST Client truy cập và sửa đổi các nguồn tài nguyên này bởi sử dụng phương thức HTTP. Ở đây mỗi nguồn tài nguyên được xác định bởi một URI. REST sử dụng các cách biểu diễn khác nhau để biểu diễn các nguồn tài nguyên như text, JSON, XML nhưng phổ biến nhất vẫn là JSON.

B. Phương thức HTTP được sử dụng trong REST

Dưới đây là các phương thức HTTP được sử dụng rộng rãi trong kiến trúc REST .

  • GET - Được sử dụng chỉ để đọc các nguồn tài nguyên.

  • PUT - Được sử đụng để tạo mới các nguồn tài nguyên.

  • DELETE - Được sử dụng để xóa các nguồn tài nguyên.

  • POST - Được sử dụng để cập nhật các bản ghi hiện tại và tạo mới nguồn tài nguyên.

C. RESTful Web Service

Một web service là một tập hợp các giao thức và chuẩn được sử dụng cho mục đích trao đối giữa ứng dụng và hệ thống. Các ứng dụng phần mềm được viết bởi các ngôn ngữ khác nhau và chạy bởi các nền tảng khác nhau có thể sử dụng web service để trao đổi dữ liệu qua mạng máy tính như internet theo các cách tương tự như trao đổi trên một máy tính.

Web service dựa trên các kiến trúc REST được biết như RESTful webservice . Những webservice này sử dụng phương thức HTTP để triển khai các định nghĩa kiến trúc REST. Một RESTful web service thường được định nghĩa một URI (kiểu như đường dẫn), Uniform Resource Identifier như một service (dịch vụ).

Tạo RESTful cho một thư viện

Giả sử chúng ta có một cơ sở dữ liệu dựa trên JSON chứa thông tin về User, tên file là users.json:

{
   "user1" : {
      "name" : "huong",
	  "password" : "password1",
	  "profession" : "sinhvien",
	  "id": 1
   },
   "user2" : {
      "name" : "manh",
	  "password" : "password2",
	  "profession" : "giangvien",
	  "id": 2
   },
   "user3" : {
      "name" : "tuyen",
	  "password" : "password3",
	  "profession" : "laptrinhvien",
	  "id": 3
   }
}

Dựa vào các thông tin cơ bản này, chúng ta sẽ cung cấp các RESTful API sau đây:

Stt URI Phương thức HTTP POST body Kết quả
1 listUsers GET empty Hiển thị danh sách user
2 addUser POST JSON String Thêm một user mới
3 deleteUser DELETE JSON String Xóa một user hiện tại.
4 :id GET empty Hiển thị chi tiết một user

Liệt kê các User

Chúng ta cùng triển khai RESTful API đầu tiên có tên listUsers bởi sử dụng đoạn code sau đây:

var express = require('express');
var app = express();
var fs = require("fs");

app.get('/listUsers', function (req, res) {
   fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
       console.log( data );
       res.end( data );
   });
})

var server = app.listen(8081, function () {

  var host = server.address().address
  var port = server.address().port

  console.log("Ung dung Node.js dang lang nghe tai dia chi: http://%s:%s", host, port)

})

Bây giờ thử truy cập API đã được định nghĩa trên bởi sử dụng http://127.0.0.1:8081/listUsers trên máy tính local. Nó sẽ cho ra kết quả sau đây:

{
   "user1" : {
      "name" : "huong",
      "password" : "password1",
      "profession" : "sinhvien",
      "id": 1
   },
   "user2" : {
      "name" : "manh",
      "password" : "password2",
      "profession" : "giangvien",
      "id": 2
   },
   "user3" : {
      "name" : "tuyen",
      "password" : "password3",
      "profession" : "laptrinhvien",
      "id": 3
   }
}

Thêm User mới

API sau chỉ ra cách thêm một User mới vào danh sách. Dưới đây là thông tin của User mới:

user = {
   "user4" : {
      "name" : "hoang",
      "password" : "password4",
      "profession" : "sinhvien",
      "id": 4
   }
}

Bạn có thể sử dụng Ajax để thực hiện việc này, nhưng để đơn giản chúng ta sẽ hard code ở đây. Dưới đây là phương thức addUser API để thêm một user mới trong cơ sở dữ liệu.

var express = require('express');
var app = express();
var fs = require("fs");

var user = {
   "user4" : {
      "name" : "hoang",
      "password" : "password4",
      "profession" : "sinhvien",
      "id": 4
   }
}

app.get('/addUser', function (req, res) {
   // Dau tien, doc tat ca cac User dang ton tai.
   fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
       data = JSON.parse( data );
       data["user4"] = user["user4"];
       console.log( data );
       res.end( JSON.stringify(data));
   });
})

var server = app.listen(8081, function () {

  var host = server.address().address
  var port = server.address().port
  console.log("Ung dung Node.js dang lang nghe tai dia chi: http://%s:%s", host, port)

})

Bây giờ thử truy cập API trên bởi sử dụng http://127.0.0.1:8081/addUsers trên máy tính local. Kết quả sẽ được hiện ra như sau:

{ user1:
   { name: 'huong',
     password: 'password1',
     profession: 'sinhvien',
     id: 1 },
  user2:
   { name: 'manh',
     password: 'password2',
     profession: 'giangvien',
     id: 2 },
  user3:
   { name: 'tuyen',
     password: 'password3',
     profession: 'laptrinhvien',
     id: 3 },
  user4:
   { name: 'hoang',
     password: 'password4',
     profession: 'sinhvien',
     id: 4 } 
}

Hiển thị thông in của User

Bây giờ cùng triển khai một API mà gọi đến userID để hiển thị chi tiết thông tin User tương ứng.

var express = require('express');
var app = express();
var fs = require("fs");

app.get('/:id', function (req, res) {
   // Dau tien, doc tat ca cac User dang ton tai.
   fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
       users = JSON.parse( data );
       var user = users["user" + req.params.id] 
       console.log( user );
       res.end( JSON.stringify(user));
   });
})

var server = app.listen(8081, function () {

  var host = server.address().address
  var port = server.address().port
  console.log("Ung dung Node.js dang lang nghe tai dia chi: http://%s:%s", host, port)

})

Tiêp đó, bạn gọi service trên bởi sử dụng địa chỉ http://127.0.0.1:8081/2 trên máy tính local. Kết quả sẽ như sau:

{
   "name":"manh",
   "password":"password2",
   "profession":"giangvien",
   "id":2
}

Xóa User

API này tương tự như addUser API, tại đây bạn có thể nhận một dữ liệu đầu vào thông qua req.body và sau đó dựa vào userID để xóa User đó khỏi Database. Để đơn giản, giả sử chúng ta xóa user có ID là 2.

var express = require('express');
var app = express();
var fs = require("fs");

var id = 2;

app.get('/deleteUser', function (req, res) {

   // Dau tien, doc tat ca cac User dang ton tai.
   fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
       data = JSON.parse( data );
       delete data["user" + 2];
       
       console.log( data );
       res.end( JSON.stringify(data));
   });
})

var server = app.listen(8081, function () {

  var host = server.address().address
  var port = server.address().port
  console.log("Ung dung Node.js dang lang nghe tai dia chi: http://%s:%s", host, port)

})

Gọi service trên bởi sử dụng http://127.0.0.1:8081/deleteUser trên máy local . Nó sẽ cho ra kết quả sau đây:

{ user1:
   { name: 'huong',
     password: 'password1',
     profession: 'sinhvien',
     id: 1 },
  user3:
   { name: 'tuyen',
     password: 'password3',
     profession: 'laptrinhvien',
     id: 3 } 
}

 

  Bài tiếp theo...

 

 


Tài liệu lập trình NodeJS

Bài viết trong cùng chuyên mục

Góc games giải trí (chơi trực tiếp trên web) Đăng nhập (chơi có thưởng)



Cờ caro


Butterfly


Lật hình (luyện trí nhớ)

Cờ tướng ONLINE

Xếp hình

Ghép hình

15_PUZZLE

Kill ghosts

Banchim

Planet Defense

Tower game

Bắn bóng

Plapy Bird (NH.Đông)

Vượt chướng ngại vật

Vẽ hình cứu người

Game Phases

Game vui chơi có thưởng

Game bắn cá



0379136392

Thông tin liên hệ: Lê Văn Thuyên - ĐT: 0379136392 ; Gmail: lethuyen0379136392@gmail.com

Comment

 +   Lê Văn Thuyên-0379136392:Cảm ơn quý vị và các bạn đã vào Website của Lê Thuyên! Lê thuyên rất mong nhận được sự góp ý của quý vị và các bạn cho sự phát triển của website này. Xin chân thành cảm ơn!

Trả lời

 *   Dũng Trung-090567448:Lê Văn Thuyên0379136392--->Ok.Anh!

Trả lời

 *   Bé Nguyễn-benguyen@gmail,com:Lê Văn Thuyên0379136392--->Good job!

Trả lời

 +   -:

Trả lời

 +   -:

Trả lời

7385