Giáo trình Mô đun Phát triển mã nguồn mở với Nodejs - Thiết kế trang Web

Thiết lập môi trường

Các đoạn code node.js thực chất là các đoạn mã Javascript. Node.js sẽ được sử

dung để thông dịch và thực thi các đoạn code Javascript.

Node.js phân phối dưới dạng các bản cài đặt cho các hệ điều hành Linux, Mac

OS X và Windown với các phiên bản 32 bit và 64 bit.

Để cài đặt Node.js các bạn có thể truy cập vào kho lưu trữ của Node.js và tải

xuống bản cài đặt phù hợp với hệ điều hành mình đang sử dụng.

Cài đặt trên Windows

Tải tệp cài đặt với định dạng .msi trên trang chủ download của Node.js

Chạy tệp cài đăt với định dạng .msi mà bạn đã tiến hành tải xuống trước đó

Làm theo hướng dẫn trong trình cài đặt.

Khởi động lại máy tính: Bạn sẽ không thể nào chạy được Node.js nếu không khởi

động lại máy tính sau khi cài đặt.

Cài đặt trên MacOs

Tải tệp cài đặt với định dạng .pkg trên trang chủ Node.Js

Mở tệp cài đặt với định dạng .pkg mà bạn vừa tải xuống

Làm theo các bước của hướng dẫn của bộ cài đặt

Cài đặt trên Linux

Với các máy chạy hệ điều hành Linux các bạn có thể cài đặt bằng cách tải xuống

và giải nén các tệp lưu trữ .tar.gz , sau đó chuyển các tệp được giải nén vào thư

mục /usr/local/nodejs

Tải tệp lưu trữ .tar.gz

Giáo trình Mô đun Phát triển mã nguồn mở với Nodejs - Thiết kế trang Web trang 1

Trang 1

Giáo trình Mô đun Phát triển mã nguồn mở với Nodejs - Thiết kế trang Web trang 2

Trang 2

Giáo trình Mô đun Phát triển mã nguồn mở với Nodejs - Thiết kế trang Web trang 3

Trang 3

Giáo trình Mô đun Phát triển mã nguồn mở với Nodejs - Thiết kế trang Web trang 4

Trang 4

Giáo trình Mô đun Phát triển mã nguồn mở với Nodejs - Thiết kế trang Web trang 5

Trang 5

Giáo trình Mô đun Phát triển mã nguồn mở với Nodejs - Thiết kế trang Web trang 6

Trang 6

Giáo trình Mô đun Phát triển mã nguồn mở với Nodejs - Thiết kế trang Web trang 7

Trang 7

Giáo trình Mô đun Phát triển mã nguồn mở với Nodejs - Thiết kế trang Web trang 8

Trang 8

Giáo trình Mô đun Phát triển mã nguồn mở với Nodejs - Thiết kế trang Web trang 9

Trang 9

Giáo trình Mô đun Phát triển mã nguồn mở với Nodejs - Thiết kế trang Web trang 10

Trang 10

Tải về để xem bản đầy đủ

pdf 72 trang duykhanh 4620
Bạn đang xem 10 trang mẫu của tài liệu "Giáo trình Mô đun Phát triển mã nguồn mở với Nodejs - Thiết kế trang Web", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

Tóm tắt nội dung tài liệu: Giáo trình Mô đun Phát triển mã nguồn mở với Nodejs - Thiết kế trang Web

Giáo trình Mô đun Phát triển mã nguồn mở với Nodejs - Thiết kế trang Web
ng 
socket ở đó, để các máy khách có thể thiết lập các kết nối khi được yêu cầu. 
Tập tin được sử dụng bới máy chủ socket.io là „/socket.io/socket.io.js„ 
Sau khi hoàn thành các yêu cầu trên tệp index.html sẽ có nội dung như sau. 
 Phạm Đình Nam – Trường Cao đẳng nghề Đà Lạt Trang 60 
 <meta name="viewport" content="width=device-width, initial-
scale=1.0"> 
 Hello World 
 Hello World 
 var socket = io(); 
Nếu bạn chạy ứng dụng và truy cập localhost:3000 bạn sẽ nhận được thông báo 
“Hello Word” trên trình duyệt. 
Để kiểm tra nhật ký ở bảng điều khiển console các bạn sẽ nhận được các thông 
báo sau. 
3. Xử lý sự kiện trong Socket.IO 
3.1 Tổng quan module Events trong Node.js 
“Module events với lớp đối tượng EventEmitter bên trong nó chính là cốt lõi của 
kiến trúc hướng sự kiện không đồng bộ trong Node.js, hầu hết các core module built-in 
trong Node.js đều kế thừa từ module events này.” 
Vậy chính xác thì module này dùng để làm gì? 
Câu trả lời đơn giản là: “Nó cho phép bạn lắng nghe các sự kiện và gán các 
hành động để chạy khi những sự kiện đó xảy ra.” 
Nếu bạn đã từng làm việc với Javascript phía trình duyệt, bạn chắc sẽ từng biết 
về các sự kiện chuột hay bàn phím khi người dùng phía client tương tác với ứng dụng 
như onclick, onkeyupvv, dựa vào những sự kiện đó mà chúng ta sẽ viết code xử lý 
hành động tiếp theo. 
Events cũng giống như vậy, ngoại trừ việc đó là chúng ta có thể tự định nghĩa sự 
kiện, phát ra sự kiện khi chúng ta muốn, không cần thiết phải dựa trên tương tác của 
người dùng. 
 Phạm Đình Nam – Trường Cao đẳng nghề Đà Lạt Trang 61 
“Module Events trong Node.js hỗ trợ cho chúng ta lập trình, viết code theo 
kiến trúc Event-Driven.” 
– “Events là một trong những lý do làm cho Node.js được nói là có tốc độ 
cao: Vì hầu hết code core của Node.js đều dựa trên mô hình Event-Driven này nên 
thay vì đọc tất cả những file cần thiết với mọi request (ví dụ như PHP). Thì thằng 
Node này lại chỉ khởi động server, khởi tạo hết các biến, khai báo các function mà 
mình viết rồi cứ thế ngồi đợi một sự kiện nào đó xảy ra và thực thi chức năng. 
– “Khi sử dụng Events thì việc ghép nối các đoạn code của chúng ta lại sẽ 
khá lỏng lẻo”: Nghĩa là khi một sự kiện được phát ra, nhưng nếu không có đoạn code 
nào lắng nghe sự kiện đó, thì cũng không sao hết, nó sẽ chẳng làm gì luôn. Như vậy 
khi cần xóa code, cụ thể là xóa một “bên lắng nghe” hoặc một “sự kiện không cần 
dùng đến nữa” thì cũng không bao giờ bị thông báo lỗi code Javascript gì cả. 
– “Sử dụng Events để thay thế cho Callbacks trong những trường hợp cụ 
thể” (không phải thay thế hoàn toàn): Node.js có rất nhiều phương thức chạy không 
đồng bộ (asynchronous), đồng nghĩa với việc có rất nhiều tác vụ liên quan đến nhau, 
tác vụ sau cần dữ liệu của tác vụ trước để chạy, nếu dùng callback thì code của bạn sẽ 
ngày càng trông giống một cái phễu lớn, người ta gọi đó là Callback Hell. 
Để ngăn chặn Callback Hell, nhiều class trong node.js đã sử dụng events để 
phát ra sự kiện, lắng nghe sự kiện và thực hiện các hành động ứng với các sự kiện. 
Như vậy sẽ tổ chức code theo một cấu trúc khác gọn gàng hơn, không gặp phải 
“callback heo” nữa. 
3.2 Sử dụng module Events. 
Sau khi đã phân tích khá nhiều lý thuyết ở trên, bây giờ chúng ta sẽ đi vào cách 
sử dụng module. 
Mình sẽ viết ví dụ đơn giản đầu tiên, Viết code để xử lý bài toán: Khi con mèo 
chạy, cái chuông trên cổ con mèo sẽ kêu ring ring. 
/** 
 Phạm Đình Nam – Trường Cao đẳng nghề Đà Lạt Trang 62 
 * Created by trungquandev.com's author on 30/09/2018. 
 */ 
const events = require("events"); 
let EventEmitter = new events.EventEmitter(); 
let ringBell = () => { 
 console.log("ring ring ring..."); 
} 
// Lắng nghe sự kiện khi mèo chạy thì gọi tới function ringBell 
EventEmitter.on("catRun", ringBell); 
// Phát sự kiện con mèo chạy. 
EventEmitter.emit("catRun"); 
Đầu tiên là nạp module events, đối tượng events này có một thuộc tính duy nhất 
đó là lớp EventEmitter. 
Bên trong EventEmitter có 2 phương thức chính là emit và on tương ứng 
với phát và lắng nghe sự kiện. 
Khi chạy EventEmitter.emit sẽ emit (phát ra) một sự kiện tên là “catRun” do 
chúng ta đặt, và rồi EventEmitter.on sẽ lắng nghe sự kiện “catRun” sau đó chạy 
function ringBell. Nếu bỏ đi một trong 2 method .emit hay .on ở trên thì chương trình 
cũng không bị lỗi gì cả. 
Ngoài ra chúng ta còn có thể include thêm dữ liệu khi emit sự kiện như thế 
này: 
EventEmitter.emit("catRun", data); 
Thì ở bên lắng nghe: 
EventEmitter.on("catRun", (data) => { 
 // Làm gì đó với data nhận được ở đây... 
}); 
Chúng ta có thể lắng nghe nhiều lần trên cùng một sự kiện như thế này: 
EventEmitter.on("catRun", (data) => { 
 // Sử dụng data cho công việc 1. 
}); 
EventEmitter.on("catRun", (data) => { 
 // Sử dụng data cho công việc 2. 
}); 
EventEmitter.on("catRun", (data) => { 
 // Sử dụng data cho công việc 3. 
}); 
 Phạm Đình Nam – Trường Cao đẳng nghề Đà Lạt Trang 63 
Mặc định Node.js cho phép 10 listeners trên cùng một sự kiện, có nghĩa là 
trong sự kiện “catRun” ở trên, Tới công việc thứ 11 Node.js sẽ thông báo lỗi. Nhưng 
không sao cả, chúng ta có thể sử dụng hàm setMaxListeners để tăng giới hạn đó. 
EventEmitter.setMaxListeners(17); // ví dụ mình nâng lên 17 listeners. 
Còn rất nhiều phương thức hay nữa như: 
.once(); .removeListener(); .removeAllListener(); .listener(); vv. 
3.3 Viết một module khác kế thừa module Events 
Trong thực tế khi viết code, sẽ còn hay hơn nữa khi mà chúng ta có thể viết một 
Class khác mà kế thừa các phương thức cũng như thuộc tính của lớp 
EventEmitter trong module events. Vì EventEmitter cũng là Javascript thông 
thường và có thể sử dụng trong các module khác. 
Nếu từng sử dụng module http của node.js, bạn có thể thấy nó cũng có một 
phương thức là .on(); 
/** 
 * Created by trungquandev.com's author on 30/09/2018. 
 */ 
var http = require("http"); 
var server = http.createServer(); 
server.on("request", function (req, res) { 
 res.end("This is the response."); 
}); 
server.listen(8017); 
Ví dụ ở trên cho thấy phương thức .on(); của lớp EventEmitter đã trở thành một 
phần của lớp http.createServer(); 
Khi server nhận được một request từ trình duyệt, nó sẽ emit một sự kiện có tên 
là “request”, sau đó một listener chính là server.on(); lắng nghe và hành động. Cụ thể 
hành động ở đây là trả về một chuỗi text: “This is the response.” 
– Bây giờ, bắt đầu ví dụ chính của chúng ta: 
“Mình sẽ viết một module UserModel.js kế thừa module events, sau đó viết một 
file index.js sử dụng chính module UserModel này mỗi khi lưu một user mới 
vào database thì sẽ emit một sự kiện thông báo là đã lưu trữ user thành công.” 
UserModel.js 
const EventEmitter = require("events").EventEmitter; 
// Fake database. 
let database = { 
 users: [ 
 {id: 1, name: "Trungquandev01", occupation: "developer"}, 
 Phạm Đình Nam – Trường Cao đẳng nghề Đà Lạt Trang 64 
 {id: 2, name: "Trungquandev02", occupation: "writer"}, 
 {id: 3, name: "Trungquandev03", occupation: "designer"} 
 ] 
}; 
class UserModel extends EventEmitter { 
 constructor() { 
 super(); // Từ khóa super được sử dụng để gọi các hàm trên đối tượng cha, ở 
đây đối tượng cha là EventEmitter 
 } 
 // Lưu user vào "database fake" ở trên. 
 saveUser(user) { 
 database.users.push(user); 
 this.emit("saved", user); // sử dụng hàm .emit của thằng EventEmitter 
 } 
 // Liệt kê toàn bộ user hiện tại. 
 allUser() { 
 return database.users; 
 } 
} 
module.exports = UserModel; 
index.js 
const UserModel = require("./UserModel"); 
let User = new UserModel(); 
// Vì đã kế thừa events nên class User có thể sử dụng method .on() 
User.on("saved", (user) => { 
 console.log(`New user saved: ${user.name} - ${user.occupation}`); 
}); 
// Lưu thêm 2 thằng user mới. 
let trungquandev04 = {id: 4, name: "Trungquandev04", occupation: "Code xịn 
(─‿‿─)"}; 
let trungquandev05 = {id: 5, name: "Trungquandev05", occupation: "Code lởm 
(-.-)"}; 
User.saveUser(trungquandev04); 
User.saveUser(trungquandev05); 
// Lấy ra toàn bộ users 
 Phạm Đình Nam – Trường Cao đẳng nghề Đà Lạt Trang 65 
let allUser = User.allUser(); 
console.log(allUser); 
Kết quả sau khi chạy: 
Như vậy, có thể thấy, module UserModel của chúng ta sau khi kế 
thừa EventEmitter, đã có thể tự phát và tự lắng nghe các sự kiện. Cool huh? =)) 😀 
3.4 Phân biệt events với socket.io 
Chắc có khá nhiều bạn khi mới làm quen với node.js thì cũng từng nghe qua cái 
tên khá phổ biến đó là socket.io để làm các ứng dụng real-time. Khi mới tìm hiểu 
Node.js mình từng cảm thấy chút mâu thuẫn giữa 2 thành phần events và 
socket.io này. 
Cả 2 module trên đều có chung một điểm là emit phát sự kiện rồi on để lắng 
nghe sự kiện và gửi – nhận các tham số dữ liệu từ chúng. 
Điểm khác quan trọng giữa 2 thành phần này đó là: 
Socket.io chỉ cho phép phát và lắng nghe sự kiện qua lại giữa client và server. 
Events chỉ cho phép phát và lắng nghe sự kiện trong nội bộ server. 
Còn nếu muốn sử dụng socket.io phát và nhận sự kiện ngay trên server 
luôn thì có một gói module khác là socket.io-client. 
4. Socket.IO Broadcasting 
Broadcasting nghĩa là gửi một tin nhắn đến tất cả người dùng đang kết nối. 
Broadcasting có thể thực hiện ở nhiều cấp độ. Chúng ta có thể gửi tin nhắn đến tất cả 
người dùng đang kết nối, khách hàng có tên bất kỳ và cả khách hàng ở trong một 
phòng cụ thể. Để phát một sự kiện cho tất cả các khách hàng, chúng ta có thể sử dụng 
phương thức io.sockets.emit 
Lưu ý: Thao tác này sẽ phát ra sự kiện cho TẤT CẢ máy khách đang được kết 
nối. 
Trong ví dụ này tôi sẽ phát ra sự kiện cho tất cả máy khách đang kết nối. Thay 
đổi nội dung file app.js như sau. 
const express = require('express'); 
const app = express(); 
const server = require('http').Server(app); 
 Phạm Đình Nam – Trường Cao đẳng nghề Đà Lạt Trang 66 
const io = require('socket.io')(server) 
app.get('/', function(request, response){ 
 response.sendFile(__dirname + '/index.html'); 
}); 
 var clients = 0; 
 io.on('connection', function(socket){ 
 clients++; 
 io.sockets.emit('broadcast', {description: `${clients} người dùng đã 
kết nối`}) 
 socket.on('disconnect', function(){ 
 clients--; 
 io.sockets.emit('broadcast', {description: `${clients} người dùng 
đã kết nối`}) 
 }) 
}); 
server.listen(8000, function(){ 
 console.log(`Lắng nghe trên cổng 8000`); 
}); 
Về phía máy khách, chúng ta tiến hành xử lý sự kiện broadcast. 
File index.html 
 <meta name="viewport" content="width=device-width, initial-
scale=1.0"> 
 Hello World 
 Hello World 
 Phạm Đình Nam – Trường Cao đẳng nghề Đà Lạt Trang 67 
 var socket = io(); 
 socket.on('broadcast', function(data){ 
 document.write(data.description) 
 }) 
Với ví dụ trên sẽ gửi tất cả sự kiện cho mọi người. Bây giờ nếu, nếu chúng ta 
muốn gửi sự kiến tới mọi người nhưng trừ máy khách gây ra sự kiện chúng ta có thể 
sử dụng socket.broadcast.emit . 
Ví dụ dưới đây, tôi sẽ gửi cho người dùng vừa kết nối một thông điệp chào 
mừng, và cập nhật cho các máy khách khách khác về việc có người vừa kết nối. 
Trong tệp app.js 
const express = require('express'); 
const app = express(); 
const server = require('http').Server(app); 
const io = require('socket.io')(server) 
app.get('/', function(request, response){ 
 response.sendFile(__dirname + '/index.html'); 
}); 
var clients = 0; 
io.on('connection', function(socket){ 
 clients++; 
 socket.emit('newclientconnect', {description: `Chào mừng bạn`}) 
 socket.broadcast.emit('newclientconnect', {description: `${clients} 
người dùng đã kết nối`}) 
 socket.on('disconnect', function(){ 
 clients--; 
 io.sockets.emit('broadcast', {description: `${clients} người dùng 
đã kết nối`}) 
 }) 
}); 
server.listen(8000, function(){ 
 console.log(`Lắng nghe trên cổng 8000`); 
}); 
 Phạm Đình Nam – Trường Cao đẳng nghề Đà Lạt Trang 68 
Xử lý sự kiện ở client 
 <meta name="viewport" content="width=device-width, initial-
scale=1.0"> 
 Hello World 
 Hello World 
 var socket = io(); 
 socket.on('newclientconnect', function(data){ 
 document.body.innerHTML = ''; 
 document.write(data.description) 
 }) 
Bây giờ khi có người mới kết nối sẽ có thông điệp chào mừng và những người đã 
kết nối trước đó sẽ nhận được có bao nhiêu người đang kết nối với máy chủ. 
5. Socket.IO Namspace 
Socket.IO cho phép bạn tạo ra “namespace” riêng cho sockets của bạn, về cơ bản 
có nghĩa là gán các điểm cuối hoặc các đường dẫn khác nhau. 
Đây là một tính năng hữu ích để giảm thiểu số lượng tài nguyên (kết nối TCP) và 
đồng thời các mối quan tâm riêng biệt của bạn trong ứng dụng bằng cách giới thiệu sự 
khác biệt giữa các kênh. 
Nhiều namspace thực sự chia sẻ cùng một kết nối Websockét do đó tiết kiệm cho 
chúng ta các cổng trên máy chủ. 
Namespace được tạo ra ở phía máy chủ. Tuy nhiên, chúng được máy khách tham 
bằng cách gửi yêu cầu đến máy chủ. 
Namespace mặc định 
 Phạm Đình Nam – Trường Cao đẳng nghề Đà Lạt Trang 69 
Namespace gốc „/‟ là namespace mặc định, được kết nối với máy khách nếu 
namespace không được chỉ định bởi client trong khi kết nối với máy chủ. Tất cả các 
kết nối đến máy chủ sử dụng phía máy khách ở đối tượng socket được thự hiện cho 
namespace mặc định. 
Ví dụ 
var socket = io(); 
Điều này sẽ kết nối máy khách với namespace mặc định. Tất cả các sự kiện trên 
kết nối namespace này sẽ được xử lý bởi đối tương io trên máy chủ. Tất cả các ví dụ 
trước đây đã sử dụng các namespace mặc định để giao tiếp với máy chủ và ngược lại. 
Namespace tùy chỉnh 
Chúng ta có thể tạo ra các namespace tùy chỉnh của riêng mình. Để thiết lập 
namespace tùy chỉnh, chúng ta có thể gọi phương thức of ở phía máy chủ. 
Thay đổi nội dung app.js như sau 
const express = require('express'); 
const app = express(); 
const server = require('http').Server(app); 
const io = require('socket.io')(server) 
app.get('/', function(request, response){ 
 response.sendFile(__dirname + '/index.html'); 
}); 
var clients = 0; 
var namespace = io.of('/my-namespace') 
namespace.on('connection', function(socket){ 
 console.log('Một người đã kết nối') 
 namespace.emit('chao', 'Chào tất cả mọi người') 
}); 
server.listen(8000, function(){ 
 console.log(`Lắng nghe trên cổng 8000`); 
}); 
 Phạm Đình Nam – Trường Cao đẳng nghề Đà Lạt Trang 70 
Tiếp theo để kết nối một máy khách với namespace này, bạn cần cung cấp 
namespace làm tham số cho lời gọi hàm tạo io để tạo một kết nối và một đối tượng 
socket ở phía máy khách. 
Ví dụ để kết nối với namespace ở trên. Cập nhật tệp index.html 
 <meta name="viewport" content="width=device-width, initial-
scale=1.0"> 
 Hello World 
 Hello World 
 var socket = io('/my-namespace'); 
 socket.on('chao', function(data){ 
 document.body.innerHTML = ''; 
 document.write(data) 
 }) 
Mỗi khi có một ai đó kết nối họ sẽ nhận được sự kiện “chao” 

File đính kèm:

  • pdfgiao_trinh_mo_dun_phat_trien_ma_nguon_mo_voi_nodejs_thiet_ke.pdf