Thứ Sáu, 15 tháng 7, 2016

PHÁT TRIỂN CÁC ỨNG DỤNG PHÍA SERVER BẰNG NODEJS-THE DEVELOPMENT OF THE SERVER SIDE APPLICATIONS BY NODEJS

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
Download và cài đặt tại địa chỉ: https://nodejs.org/en/download/
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/

1 nhận xét: