# 為什么應該使用流
在node中,I/O都是異步的,所以在和硬盤以及網絡的交互過程中會涉及到傳遞回調函數的過程。你之前可能會寫出這樣的代碼:
~~~
var http = require('http');
var fs = require('fs');
var server = http.createServer(function (req, res) {
fs.readFile(__dirname + '/data.txt', function (err, data) {
res.end(data);
});
});
server.listen(8000);
~~~
上面的這段代碼并沒有什么問題,但是在每次請求時,我們都會把整個`data.txt`文件讀入到內存中,然后再把結果返回給客戶端。想想看,如果`data.txt`文件非常大,在響應大量用戶的并發請求時,程序可能會消耗大量的內存,這樣很可能會造成用戶連接緩慢的問題。
其次,上面的代碼可能會造成很不好的用戶體驗,因為用戶在接收到任何的內容之前首先需要等待程序將文件內容完全讀入到內存中。
所幸的是,`(req,res)`參數都是流對象,這意味著我們可以使用一種更好的方法來實現上面的需求:
~~~
var http = require('http');
var fs = require('fs');
var server = http.createServer(function (req, res) {
var stream = fs.createReadStream(__dirname + '/data.txt');
stream.pipe(res);
});
server.listen(8000);
~~~
在這里,`.pipe()`方法會自動幫助我們監聽`data`和`end`事件。上面的這段代碼不僅簡潔,而且`data.txt`文件中每一小段數據都將源源不斷的發送到客戶端。
除此之外,使用`.pipe()`方法還有別的好處,比如說它可以自動控制后端壓力,以便在客戶端連接緩慢的時候node可以將盡可能少的緩存放到內存中。
想要將數據進行壓縮?我們可以使用相應的流模塊完成這項工作!
~~~
var http = require('http');
var fs = require('fs');
var oppressor = require('oppressor');
var server = http.createServer(function (req, res) {
var stream = fs.createReadStream(__dirname + '/data.txt');
stream.pipe(oppressor(req)).pipe(res);
});
server.listen(8000);
~~~
通過上面的代碼,我們成功的將發送到瀏覽器端的數據進行了gzip壓縮。我們只是使用了一個oppressor模塊來處理這件事情。
一旦你學會使用流api,你可以將這些流模塊像搭樂高積木或者像連接水管一樣拼湊起來,從此以后你可能再也不會去使用那些沒有流API的模塊獲取和推送數據了。