Nhắc đến Stream chúng ta liên tưởng đến ngay khái niệm về một cách xử lý dữ liệu rất mơ hồ, giữa việc sử dụng một đầu vào và đưa nó vào một đích nào đó. Trong bài viết này, Stringee và các bạn sẽ cùng nhau tìm hiểu về Stream trong Node.js nhé.

1. Stream là gì?

Stream là đối tượng cho phép chúng ta nhận dữ liệu từ một nguồn và có thể ghi nó tới một đích. Node.js hiện đang có bốn loại Stream được hỗ trợ:

  • 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.

Stream là một sự thể hiện của đối tượng EventEmiiter và nó sẽ ném ra một sự kiện tùy thời điểm. Dưới đây là danh sách 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ở.

2. Sử dụng Stream để đọc dữ liệu trong Node.js

Trong phần này, chúng ta sẽ cùng tìm hiểu cách sử dụng Stream để đọc dữ liệu bằng cách phân tích ví dụ đọc một file và hiển thị nội dung file đó ra màn hình.

Để bắt đầu, chúng ta cần khai báo module fs. Việc khai báo này là để chúng ta có thể sử dụng module fs cho các hoạt động I/O với file. Sau đó sử dụng phương thức createReadStream() nhận tham số là đường dẫn của file text để đọc dữ liệu từ đó.

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

var readerStream = fs.createReadStream('./file_text.txt')
readerStream.setEncoding('UTF-8')

readerStream.on('data', function(chunk){
  data += chunk
})

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

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

console.log('end program')

Chúng ta sẽ chạy file này để xem kết quả:

node Stream_input.js

Kết quả hiển thị ra console sẽ là:

end program
Hello world

Như đã phân tích ở trên, chúng ta có thể đăng ký các sự kiện thay đổi bằng phương thức on, dựa trên từng sự kiện chúng ta có thể thực hiện các hành động tương ứng như là cộng vào chuỗi kết quả, dừng chương trình và in ra lỗi…

>>> Xem thêm bài viết:

HTTP là gì? Tìm hiểu về giao thức HTTP và HTTPS

HTTP request là gì? Các phương thức HTTP request

Hướng dẫn cài đặt unix linux 

3. Ghi dữ liệu vào Stream trong Node.js

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

var writerStream = fs.createWriteStream('output.txt');
writerStream.write(data,'UTF8');
writerStream.end();

writerStream.on('finish', function() {
    console.log("Finish process write");
});
writerStream.on('error', function(err){
   console.log(err.stack);
});

console.log("Program end!");

Chạy chương trình ta thấy console:

Program end!
Finish process write

Kiểm tra file output.txt:

~ cat output.txt 
Hi world%

4. Piping Stream trong Node.js

Pipe là một kỹ thuật mà ở đây chúng ta sẽ cung cấp kết quả đầu ra của một Stream để làm đầu vào cho một Stream khác. Quá trình này không có giới hạn, tức là bạn có thể tiếp tục quá trình mà không lo ngại việc bị kết thúc sớm do giới hạn thời gian, số đầu ra đầu vào.

Ví dụ dưới đây là một ví dụ cho việc sử dụng piping Stream trong Node.js. Chúng ta 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");
var data = '';

var readerStream = fs.createReadStream('output.txt');
var writerStream = fs.createWriteStream('output-2.txt');

readerStream.pipe(writerStream);
console.log("End this program");

Xem nội dung của file sẽ được copy từ file output cũ:

~ cat output-2.txt 
Hi world%  

Ta có thể thấy nội dung giống hoàn toàn với file output.txt từ ví dụ trước đó.

5. 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 này 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 đó. Chúng ta cùng nhau thực hiện. 

Đầu tiên, tạo một file input.txt để đối chiếu:

echo "This is input" >> input.txt

Chương trình sẽ như sau:

var fs = require("fs");
var zlib = require('zlib');
 
fs.createReadStream('input.txt')
   .pipe(zlib.createGzip())
   .pipe(fs.createWriteStream('input.txt.gz'));
   
console.log("Zipped input.txt to input.txt.gz!");

Chạy file source và kiểm tra kết quả:

~ node chaining_Stream.js 
Zipped input.txt to input.txt.gz!

~ ls -l|grep input
-rw-r--r--    1 user  staff        14 Feb 22 22:54 input.txt
-rw-r--r--    1 user  staff        31 Feb 22 22:55 input.txt.gz

Ta có thể thấy sau một loạt các piping thì chúng ta đã tạo ra được một file zip từ file input.

Kết

Stream là một kiến thức rất cần để bạn có thể trở thành một lập trình viên có kiến thức tốt vì bản thân nó được sinh ra là để giải quyết các vấn đề liên quan đến sự lạm phát bộ nhớ của bạn. Làm chủ được kỹ thuật này sẽ giúp chương trình của bạn có thể chạy trơn tru và mượt mà hơn.


Stringee Communication APIs là giải pháp cung cấp các tính năng giao tiếp như gọi thoại, gọi video, tin nhắn chat, SMS hay tổng đài CSKH cho phép tích hợp trực tiếp vào ứng dụng/website của doanh nghiệp nhanh chóng. Nhờ đó giúp tiết kiệm đến 80% thời gian và chi phí cho doanh nghiệp bởi thông thường nếu tự phát triển các tính năng này có thể mất từ 1 - 3 năm.

Bộ API giao tiếp của Stringee hiện đang được tin dùng bởi các doanh nghiệp ở mọi quy mô, lĩnh vực ngành nghề như TPBank, VOVBacsi24, VNDirect, Shinhan Finance, Ahamove, Logivan, Homedy,  Adavigo, bTaskee…

Quý bạn đọc quan tâm xin mời đăng ký NHẬN TƯ VẤN TẠI ĐÂY: