PHÁT TRIỂN
CÁC ỨNG DỤNG PHÍA SERVER
BẰNG NODEJS
THE
DEVELOPMENT OF THE SERVER SIDE APPLICATIONS
BY NODEJS
Bùi Hương Đông
Nguyễn Minh Hải
TÓM TẮT
Javascript là ngôn ngữ phía client (client-side),
còn để thực hiện những công việc về phía server thì chúng ta thưởng sử dụng các
ngôn ngữ lập trình như PHP, Ruby,.. Nhưng khi Nodejs ra đời nó cho
phép các nhà phát triển ứng dụng sử dụng Javascript để lập trình cho các ứng
dụng phía server (server side), với
Nodejs thì javascript có thể thao tác và xử lý dữ liệu trên server như các ngôn
ngữ lập trình phía server khác.
Keyword: Nodejs, JavaScipt
ABTRACT
JavaScript is a client-side
language, we generally use programming languages such as PHP, Ruby... to perform
work on the server side. But when Nodejs was invented, it allows application
developers to use JavaScript to program the server-side applications.
Javascript can manipulate and process data on the server like the other
server-side programming languages with Nodejs.
1.
Giới thiệu
JavaScript là ngôn ngữ lập trình
dùng để tạo ra các trang web có tính tương tác với người dùng, các hiệu ứng như
slideshow, pop-up quảng cáo.., Tuy nhiên, JavaScipt không được xem là một ngôn
ngữ phát triển như các ngôn ngữ phía server như Java, Ruby hay Python. JavaScript
chỉ là một ngôn ngữ lập trình phía client chạy trên trình duyệt; để chạy
JavaScipt trên server người ta dùng Nodejs.
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 Nodejs được viết bằng Javascript và có thể chạy trong môi trường
Nodejs trên hệ điều hành Window, Linux... Ngoài ra Nodejs 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 [3].
JavaScript hiện nay là một trong
những ngôn ngữ yêu thích để phát triển
các ứng dụng web và Nodejs được sử dụng làm nền tảng server-side bởi các
website và dịch vụ nổi tiếng như eBay, GE, GoDaddy, Microsoft, Paypal, Uber.... [3].. Việc có thể sử dụng
cùng một ngôn ngữ trên cả phần front-end và back-end làm cho việc phát triển
các ứng dụng trở nên dễ dàng hơn.
Bài báo này được tổ chức như sau:
Trong phần tiếp theo, chúng tôi hướng dẫn cách cài đặt Nodejs, cách tạo một máy
chủ http cơ bản để có thể trao đổi dữ liệu với trình duyệt, cách định tuyến cơ
bản dựa vào thư viện Express của Nodejs và trình quản lý gói NPM (Node Package
Manager) để tiện cho việc quản lý, cài đặt các module...Phần 3 giới thiệu một
số cơ chế blocking hay non-blocking, khái niệm về Event loop, những thành phần
làm cho chương trình sử dụng Nodejs trở nên nhanh chóng, mạnh mẽ và phần cuối
cùng là kết luận.
2.
Cài đặt và xây dựng máy chủ http cơ
bản
2.1 Cài đặt và sử dụng Nodejs trên Window
Sử dụng file MSI và các hướng dẫn
hiện lên khi cài đặt Nodejs. Mặc định, bộ cài đặt Nodejs được lưu trữ tại
C:\Program Files\nodejs. Để xác nhận quá trình cài đặt Nodejs có thành công hay
không ta tạo một file js với tên main.js trên máy tính với nội dung sau:
Console.log(“hello,
world”);
Sử dụng trình biên dịch nodejs (từ cửa sổ lệnh)
để xem kết quả:
$node main.js
Nếu thành công, sau khi biên dịch sẽ cho kết
quả dòng “hello, world”.
Hình 2.1. Thực thi chương trình Nodejs.
2.2 NPM: Node Package Manager
Cung cấp các tiện ích để cài đặt gói
Nodejs, quản lí version,... để cài đặt các module trong các ứng dụng Nodejs
người ta sử dụng npm. Có hai cách để cài đặt module trong nodejs:
2.2.1. Cài đặt Module với command prompt
Cú pháp để cài đặt một module trong
Nodejs như sau:
$ npm install <module Name>
Ví dụ: Để cài đặt một module rất phổ
biến trong Nodejs, đó là express.
$ npm install express
Để sử dụng module này trong file js
ta phải khai báo cú pháp sau:
var express=require(‘express’);
Hình 2.3 Cài đặt module express
trong Nodejs.
2.2.2. Cài đặt module trong
NPM sử dụng package.json
Cú pháp để tạo file package.json trong thư mục
của chương trình :
$ npm init
Hình 2.4 Nội dung của file
package.json
Trong đó:
·
Name - Tên của gói
·
version - phiên bản của
gói
·
description - Mô
tả của gói
·
author - tác giả của
gói
·
contributors -
tên của người đóng góp vào gói
·
dependencies - danh sách phụ thuộc. NPM tự động cài đặt tất
cả các phụ thuộc được đề cập ở đây trong thư mục node_module của gói.( ở đây là
gói express phiên bản 4.14.0)
·
repository - loại
kho lưu trữ và địa chỉ của các gói
·
keywords - từ khóa
Để cài đặt các gói
trong dependencies của file package.json ta dùng
lệnh:
$ npm install
2.3.Modul trong Nodejs
Nodejs 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 giống như các thư viện
trong C, C#, Java,… Để sử dụng một module chúng ta chỉ cần khai báo hàm
require(), như sau:
var http=require(‘http’);
Ở
đây require() là hàm trả về tham chiếu tới một Module cụ thể. Trong trường hợp
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. Đ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.
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, ví dụ như sau:
var p=3,14;
export.dientich=function(bankinh){
return pi*bankinh*bankinh;
};
export.chuvi=function(bankinh){
return 2*pi*r;
};
Đoạn mã trên tạo ra một biến p 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().
2.1
Xây dựng máy chủ http cơ bản
2.1.1. Xây dựng máy
chủ http cơ bản
Nodejs cung cấp giao diện máy chủ thông qua
module http, và được khai báo như sau:
var http = require('http');
Để tạo ra một HTTP server, Nodejs
gọi hàm http.createServer(). Tham số của
hàm createServer() là một hàm callback (hàm đóng vai trò là tham số của của một
hàm khác). Trong hàm callback này bao gồm hai tham số request (req)
và response(res) (server đọc các request từ client và trả
về các phản hồi cho trình duyệt) [1].
Xét đoạn mã sau:
var http = require('http');
var server = http.createServer(function(req,
res){ [1]
res.end('Hello World');
});
server.listen(3000);
Ở đây chúng ta gửi trả về trình duyệt bằng cách
gọi method write từ response:
res.write('Hello World');
Tuy nhiên để hoàn thành quá trình kết nối giữa
server (Node.js) và client (trình duyệt) và chúng ta gọi method end:
res.end();
Chúng ta vừa viết xong một máy chủ HTTP có khả
năng hoạt động tốt. Thực hiện chạy lệnh:
$node server.js
Và kiểm địa
chỉ ở trình duyệt ta có kết quả:
Hình 2.5 Xây dựng
server http cơ bản
2.2.2. Sử dụng module express để
định tuyến trong Nodejs.
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. [3].
Xét ví dụ sau:
var express = require('express');
var app = express(); //khai báo thư viện express
// Định tuyến cho trang chủ
app.get('/', function (req, res) {
console.log("Got a GET
request for the homepage");
res.send('Hello GET');
})
// Phản hồi cho GET request của trang /list_user page. [3]
// Đọc dữ liệu trong file user.json trong thư mục của chương trình
app.get('/listUsers', function (req, res) {
fs.readFile( __dirname +
"/" + "users.json", 'utf8', function (err, data) {
console.log( data );
res.end( data );
});
})
// Phản hồi cho GET request của
trang các trang abcd, abxcd, ab123cd, and so on
app.get('/ab*cd', function(req, res) {
console.log("Got a GET
request for /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("Example app
listening at http://%s:%s", host, port)
})
Thực hiện chạy lệnh: $node
server.js
Kiểm tra kết quả trên trình duyệt:
Trang chủ:
Hình 2.6 Kết quả thực
thi chương trình
Trang /list_user: (Đọc dữ liệu từ
file user,json và list ra màn hình)
Hình 2.7 Định tuyến cho trang listUsers
Trang: /ab**cd
Hình 2.8 Định tuyến cho nhiều trang.
3.
Non-blocking và Event Loop trong
Nodejs
3.1.Blocking code và
Non-blocking Code trong Nodejs.
Ta có hai đoạn code sau:
Blocking-code:
var fs=require('fs');
var
data=fs.readFileSync("input.txt");
console.log(data.toString()); [3]
console.log('ket thuc');
Non-blocking-code:[tham chiếu]
var fs=require('fs');
fs.readFile("input.txt", function(err,
data){
if (err) return
console.log(err);
console.log(data.toString());
});
console.log('ket
thuc');
Kết quả:
Blocking code
|
Non-Bloking code
|
Hính 3.1 –
Kết quả thu được
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
(block) 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” cùng thời
điểm thực hiện chương trình. Cơ chế lập trình non-blocking cho phép chương
trình thực thi mạnh mẽ, do đó xử lý được lượt request lớn đồng thời.
3.2. Khái niệm Event Loop
trong Nodejs
Javascript xử lý một dòng lệnh tại
cùng một thời điểm như thế nào? Nó sử dụng một Call stack.
Để hiểu rõ Call stack hoạt động như thế nào chúng ta xét ví dụ sau:
var firstFunction = function ()
{
console.log("I'm first!");
};
var secondFunction = function ()
{ [2]
firstFunction();
console.log("I'm second!");
};
secondFunction();
Kết quả:
Hình 3.2 –
Minh họa sau khi thực thi chương trình
Chương trình trên được thực thi như
sau:
Hình 3.3 Minh họa Call Stack
Đầu tiên firstFunction được thực thi hiễn thị ra màn hình “I’m first” và do không còn dòng code
nào trong firstFunction nữa firstFunction sẽ được xóa ra khỏi Cal stack, tiếp đó secondFunction
tiếp tục chạy in ra màn hình "I'm
second!" -> secondFunction cũng được xóa ra khỏi stack ->chương trình chính không còn dòng
lệnh nào nữa nó cũng được xóa ra khỏi stack.
Tiếp theo, ta xét ví dụ sau:
[Tham chiếu]
var firstFunction = function ()
{
console.log("I'm first!");
};
var secondFunction = function ()
{
setTimeout(firstFunction, 5000);
console.log("I'm second!");
};
secondFunction();
Kết quả:
Sau khi secondFunction được gọi thì Call stack như sau:
Hình 3.4 –
Kết quả thực thi
Hình 3.5 – Minh họa Call Stack
Ngay sau khi hàm
setTimeout thực thi, browser đặt hàm callback của setTimeout (trong trường hợp
này là hàm firstFunction, hàm đóng vai trò là tham số trong hàm setTimeout) vào
trong một Event table (bảng sự kiện). Khi sự kiện setTimeout xảy ra, Event
table chỉ đơn giản di chuyển hàm firstFunction
sang Event queue (hàng đợi).
Để chuyển các hàm từ
Event queue sang Call stack
Javascript thực hiện như sau: Luôn có một tiến trình liên tục kiểm tra có Call stack nào rỗng không, tiếp đến nó
kiểm tra trong Event Queue có hàm nào đang đợi hay không, nếu có thì hàm đầu
tiên trong Event Queue sẽ được chuyển sang Call
stack để xử lý. Các quá trình trên được gọi là Event loop [2]. Event loop
liên tục kiểm tra Call stack và hiện
tại nó phát hiện call stack đang rỗng nên gọi firstFunciton và tạo ra một Call stack mới và thực thi nó để
in ra màn hình câu “I’m First!”.
4. Kết Luận
Qua bài viết này, ta có
thể có một cái nhìn tổng quát về Nodejs như: làm sao để Javascript một ngôn ngữ
phía client có thể thao tác như những ngôn ngữ phía server. Với cơ chế
Non-blocking, Event loop... cho phép chương trình thực thi nhanh chóng, mạnh
mẽ, do đó xử lý được lượt request lớn đồng thời... Ngoài ra với tình quản lý
gói (NPM) nodejs cung cấp nhiều module hỗ trợ cho công việc phát triển ứng
dụng, chúng ta có thể giảm thiểu được nhiều thời gian vì không cần phải viết
nhiều đoạn mã.
Với những ưu thế sẵn có
đó Nodejs ngày càng trở nên được ưa chuộng và sử dụng trong các công ty lớn và
được các lập trình viên yêu thích sử dụng.
Tài liệu tham khảo
[1] Mike Cantelon, Marc Harter, T.J.
Holowaychuk, Nathan Rajlich, “Node.js in
Action “ ,2014 by Manning Publications Co.
[2] https://techmaster.vn/posts/33416/hoc-lap-trinh-web-javascript
[3]http://www.tutorialspoint.com/nodejs/












The first....
Trả lờiXóa