Category Archives: NodeJS

NodeJS – Sử dụng Node

Trong phần này chúng ta sẽ tìm hiểu cách sử dụng Node.

Chạy file mã nguồn Node

Bạn có thể mở terminal lên và gõ lệnh node --help để xem hướng dẫn sử dụng Node (bằng tiếng Anh).

C:\User\PhoCode>node --help
Usage: node [options] [ -e script | script.js ] [arguments]
...

Ngay dòng đầu tiên là cách để chạy một file node, chỉ đơn giản là ghi lệnh node <tên file> ra là được, nếu muốn có thể thêm một số tùy chọn (options) và tham số đi kèm (arguments).

Bạn có thể dùng bất cứ trình editor nào để viết code đều được. Dĩ nhiên là chúng ta nên dùng những editor có chức năng hiển thị code (tức là có thể in màu những từ khóa như Notepad++…) để làm việc cho dễ.

Ví dụ:

var fs = require('fs');
var files = fs.readdirSync('.');
for (fn in files) {
    console.log(files[fn]);
}

Chúng ta tạo một file có tên ls.js với đoạn code như trên. File này mình đặt ở thư mục C:\, bạn có thể đặt ở đâu cũng được, tốt nhất là nên tạo thư mục riêng để đặt cho dễ quản lý.

Tiếp theo chúng ta chạy file đó bằng cách gõ lệnh:

C:>node ls.js
Intel
Logs
PerfLogs
Program Files
Program Files(x86)
Users
Windows

Đoạn code trên làm công việc liệt kê danh sách các file và thư mục của thư mục hiện tại, tức là thư mục chứa file ls.js, nếu bạn đã từng dùng các hệ điều hành Unix thì bạn cũng biết là lệnh ls là lệnh có chức năng tương tự có trong các hệ điều hành đó cho nên mình mới đặt là ls.js.

Chúng ta sẽ tìm hiểu chi tiết chức năng của từng dòng code ở các bài sau. Bây giờ chúng ta sẽ tìm hiểu cách truyền tham số vào khi chạy. Đoạn code trên sửa lại như sau:

var fs = require('fs');
var dir = '.';
if (process.argv[2])
    dir = process.argv[2];
var files = fs.readdirSync(dir);
for (fn in files) {
    console.log(files[fn]);
}

Khi chạy chúng ta có thể thêm tham số là đường dẫn một thư mục bất kì vào sau tên file. Ví dụ:

C:>node ls.js C:\Windows
addins
appcompat
AppPatch
AppReadiness
assembly
...

Khi chạy, đường dẫn C:\Windows sẽ được truyền vào một biến mảng toàn cục có tên là process.argv, mảng này luôn luôn chứa ít nhất là 2 phần tử, phần tử đầu tiên là đường dẫn đến file node.exe trong thư mục cài đặt Node, phần tử thứ 2 là đường dẫn đến file sẽ được dịch để chạy, ở đây là file ls.js, và các phần tử tiếp theo nếu có, ở đây là C:\Windows.

Tạo web server

Vì Node được phát minh để làm web nên hầu hết chúng ta sẽ viết web server rất nhiều trong suốt series này. Ở đây chúng ta sẽ viết một đoạn code nhỏ để kiểm tra thử:

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type' : 'text/plain'});
    res.end('Hello, World\n');
}).listen(8124, '127.0.0.1');
console.log('Server running at http://127.0.0.1:8124');

Chúng ta tạo một file có tên app.js và viết đoạn code trên vào. Sau đó chạy:

C:>node app.js
Server running at http://127.0.0.1:8124

Đây chỉ là một đoạn code đơn giản, chúng ta sẽ tìm hiểu thêm sau. Sau khi đã chạy thì chúng ta có thể mở trình duyệt lên và trỏ đến 127.0.0.1:8124 hoặc localhost:8124 để xem chuỗi trả về của server.

capture

Bạn cũng lưu ý là đoạn code trên sẽ chạy vô thời hạn cho đến khi chúng ta ngắt chương trình (như bấm Ctrl+C trong terminal) chứ không giống như các đoạn code trước là chạy xong thì kết thúc.

Phần mềm quản lý gói – npm

Bản thân Node không có gì đặc sắc, chỉ là một trình biên dịch JavaScript với một vài thư viện nhập xuất bất đồng bộ. Lý do Node phát triển mạnh là vì nó là mã nguồn mở, đặc trưng của mã nguồn mở là cộng đồng hỗ trợ rất lớn, có rất nhiều coder ngoài viết thư viện hỗ trợ cho Node. Bản thân Node có một phần mềm quản lý các gói thư viện này đó là npm. Chúng ta có thể tải các gói thư viện về và sử dụng ngay một cách dễ dàng với npm.

Ở các phiên bản cũ thì chúng ta phải cài npm riêng khi cài Node, còn đối với các phiên bản mới thì khi chúng ta cài Node thì npm cũng đã được cài sẵn rồi.

Chúng ta sẽ thử cài gói hexy với npm, đây là một công cụ cho phép xem địa chỉ bộ nhớ của từng byte trong một file dưới dạng số hệ 16. Để cài một gói thì chúng ta chạy lệnh npm install [tùy chọn] <tên gói>:

C:>npm install -g hexy
C:\Users\PhoCode\AppData\Roaming\npm\hexy -> C:\Users\PhoCode\AppData\Roaming\npm\node_modules\hexy\bin\hexy_cmd.js
hexy@0.2.7 C:\Users\Gigabyte\AppData\Roaming\npm\node_modules\hexy

Tùy chọn -g cho biết gói này được cài đặt toàn cục (globally), tức là ai cũng có thể dùng.

Sau đó chúng ta chạy thử gói này, ví dụ:

C:>hexy ls.js
00000000: 636f 6e73 6f6c 652e 6c6f 6728 7072 6f63 console.log(proc
00000010: 6573 732e 6172 6776 5b30 5d29 3b0d 0a63 ess.argv[0]);..c
00000020: 6f6e 736f 6c65 2e6c 6f67 2870 726f 6365 onsole.log(proce
00000030: 7373 2e61 7267 765b 315d 293b 0d0a 7661 ss.argv[1]);..va
00000040: 7220 6673 203d 2072 6571 7569 7265 2827 r.fs.=.require('
00000050: 6673 2729 3b0d 0a76 6172 2064 6972 203d fs');..var.dir.=
00000060: 2027 2e27 3b0d 0a69 6620 2870 726f 6365 .'.';..if.(proce
00000070: 7373 2e61 7267 765b 325d 290d 0a20 2020 ss.argv[2]).....
00000080: 2064 6972 203d 2070 726f 6365 7373 2e61 .dir.=.process.a
00000090: 7267 765b 325d 3b0d 0a76 6172 2066 696c rgv[2];..var.fil
000000a0: 6573 203d 2066 732e 7265 6164 6469 7253 es.=.fs.readdirS
000000b0: 796e 6328 6469 7229 3b0d 0a66 6f72 2028 ync(dir);..for.(
000000c0: 666e 2069 6e20 6669 6c65 7329 207b 0d0a fn.in.files).{..
000000d0: 2020 2020 2f2f 636f 6e73 6f6c 652e 6c6f ....//console.lo
000000e0: 6728 6669 6c65 735b 666e 5d29 3b0d 0a7d g(files[fn]);..}
000000f0: 0d0a ..

Nếu máy của bạn in ra mấy dòng tương tự như trên thì gói hexy đã được cài đặt thành công.

NodeJS – Cài đặt

Trước khi đi vào tìm hiểu các thành phần của Node thì chúng ta phải cài đặt Node trên máy đã.

Node có thể chạy trên hầu hết các hệ điều hành, từ Linux, MacOS X… cho đến Windows. Ngoài ra các máy tính nhỏ cũng có thể chạy được, như các CPU trên thiết bị di động ARM, Raspberry Pi…

Chúng ta có thể cài Node thông qua các hệ thống quản lý gói có sẵn trên các hệ điều hành UNIX (như apt-get trên Ubuntu, yum trên CentOS…), thông qua trình Installer trên Windows, hoặc build lại từ Source, mặc dù việc build từ source là khá khó và không nên dùng cách này vì phí thời gian.

Cài đặt trên các hệ điều hành UNIX

Đối với các hệ điều hành UNIX thì chúng ta sẽ sử dụng phần mềm quản lý gói có sẵn trong các hệ điều hành này. Việc dùng các chương trình này có một thuận lợi là chúng ta có thể cập nhật phiên bản mới nhất mọi lúc mọi nơi chỉ với một câu lệnh, ví dụ apt-get update. Và trước khi cài Node thì chúng ta cũng nên chạy câu lệnh này trước.

Sau đó để cài Node thì chúng ta gõ lệnh sau:

Với Debian:

$ apt-get install nodejs

Với Ubuntu:

$ sudo apt-get install python-software-properties
$ sudo add-apt-repository ppa:chris-lea/node.js
$ sudo apt-get update
$ sudo apt-get install nodejs npm

Vậy là xong.

Cài đặt trên Windows

Để cài đặt trên Windows thì cách tốt nhất là chúng ta lên trang chủ của Node và tải trình Installer về cài đặt tại địa chỉ https://nodejs.org/en/download/

Sau đó chúng ta tiến hành cài đặt như bình thường. Lưu ý trong quá trình cài đặt chúng ta nên chọn để trình Installer gán địa chỉ thư mục vào biến môi trường PATH. Nếu không sau này khi code sẽ rất mệt.

capture

Kiểm tra phiên bản Node

Sau khi đã cài đặt thành công. Chúng ta có thể mở trình terminal (trong Windows là Command Prompt – cmd) lên và chạy lệnh node -v hoặc node --version để xem phiên bản Node trên máy cũng như kiểm tra xem Node đã được cài đặt thành công hay chưa.

C:\User\PhoCode>node -v
v4.5.0

NodeJS – Giới thiệu

 

Node là một nền tảng phát triển các ứng dụng web back-end được viết bằng JavaScript, tức là Node không được viết để chạy trên trình duyệt, nếu bạn đã từng học JavaScript thông thường thì bạn sẽ thấy Node chạy khác với những gì bạn đã học, bạn sẽ không thấy những thứ như document.getElementById()... mặc dù thực tế vẫn có một số thư viện hỗ trợ Node viết cho trình duyệt, tuy nhiên chúng ta sẽ không quan tâm đến chúng trong series này.

Ngoài việc chạy trên JavaScript thì Node có những tính năng đi kèm sau:

  • Có trình CLI (giao diện dòng lệnh)
  • Chạy theo mô hình REPL
  • Có các hàm quản lý tiến trình
  • Có các đối tượng hỗ trợ làm việc với dữ liệu nhị phân
  • Hỗ trợ TCP và UDP
  • Hỗ trợ hân giải DNS
  • Hỗ trợ HTTP và HTTPS
  • Có thể truy cập file và thư mục

Node cho phép bạn thực hiện các giao thức mạng ở cấp độ thấp một cách dễ dàng. Chẳng hạn như Node có module HTTP cho phép xây dựng một webserver chỉ với vài dòng code, tuy nhiên vì thế mà bạn sẽ phải học nhiều thứ hơn như học về các header của một gói tin HTTP, không như PHP vốn chỉ là một module mở rộng của một webserver có sẵn (như Apache hay NginX…) – tức là PHP dễ dùng hơn Node nhưng lại không cho phép coder thực hiện các công việc ở cấp độ thấp. Tuy nhiên vì NodeJS là một framework mã nguồn mở, do đó trên mạng cũng có một số thư viện hỗ trợ viết webserver nhanh hơn và dễ hơn cho coder.

Kiến trúc của Node

Node sử dụng kiển trúc lập trình hướng sự kiện không đồng bộ, và đây là một tính năng làm cho các ứng dụng Node có thể chạy với hiệu suất cao. Chẳng hạn như đối với các ứng dụng bình thường như một chương trình viết bằng C++ thì khi chúng ta viết chương trình để đọc dữ liệu, chương trình sẽ phải dừng lại ở đoạn code đọc dữ liệu để chờ cho đến khi có dữ liệu để đọc, nếu muốn chương trình tiếp tục vừa chạy các công việc khác vừa đọc dữ liệu thì phải dùng đến đa luồng (multi-threading), tuy nhiên việc dùng đa luồng rất phức tạp và có thể làm chậm server.

Node chỉ sử dụng một luồng duy nhất, các câu lệnh nhập xuất không cần phải chờ bằng cách sử dụng Event Loop, cứ mỗi lần có sự kiện xảy ra thì chuyển dữ liệu của sự kiện đó đến các hàm xử lý tương ứng, và trong khi các hàm xử lý đang chạy thì vòng lặp sự kiện vẫn tiếp tục nhận sự kiện và chuyển đến các hàm xử lý tương ứng khác.

Ví dụ giả sử chúng ta có dòng code lấy dữ liệu từ cơ sở dữ liệu như sau:

result = query('SELECT * from db');
// xử lý result

Đối với các chương trình bình thường thì khi chạy đến dòng code trên, luồng chạy chương trình đó sẽ phải dừng lại để đợi quá trình xử lý từ cơ sở dữ liệu thực hiện xong và trả về rồi mới tiếp tục được, trong quá trình đợi đó sẽ có nhiều yêu cầu khác xảy ra và hiệu suất phần mềm sẽ giảm do lãng phí tài nguyên, để giải quyết tình trạng đó thì chúng ta có thể dùng cơ chế đa luồng để xử lý, tuy nhiên đa luồng có một nhược điểm làm tiêu tốn nhiều bộ nhớ và CPU.

Thay vì dùng đa luồng thì Node sử dụng cơ chế Event Loop để giải quyết việc này, nói một cách đơn giản thì Node sẽ đưa các câu lệnh chờ trên vào một luồng khác là Event Loop để xử lý riêng, trong khi luồng chính vẫn sẽ chạy các công việc của riêng nó, và khi nào luồng chính “rảnh” rồi thì luồng Event Loop sẽ chuyển các công việc đã thực hiện xong trở về lại luồng chính. Và chính vì Node chỉ sử dụng 2 luồng nên tài nguyên hệ thống sẽ không bị chiếm nhiều như khi dùng cơ chế đa luồng, ngoài ra việc code sử dụng Event Loop đơn giản hơn nhiều, ví dụ:

query('SELECT * from db', function(err, result) {
    if (err) throw err;
    // xử lý result
});

Trong đoạn code trên, kết quả trả về từ hàm query() thay vì được gán vào một biến thì sẽ được truyền vào một hàm khác là function(err, result){...}, và hàm này sẽ được chuyển vào luồng Event Loop và chờ cho đến khi luồng chính “rảnh” thì mới được chuyển qua.

Tên gọi

Tên chính thức là Node.js, tuy nhiên chúng ta sẽ gọi tắt là Node cho đơn giản.