浅谈Node IO操作
學習Node就繞不開異步IO, 異步IO又與事件循環息息相關, 而關于這一塊一直沒有仔細去了解整理過, 剛好最近在做項目的時候, 有了一些思考就記錄了下來, 希望能盡量將這一塊的知識整理清楚, 如有錯誤, 請指點輕噴~~
同步異步 & 阻塞非阻塞
查閱資料的時候, 發現很多人都對異步和非阻塞的概念有點混淆, 其實兩者是完全不同的, 同步異步指的是行為即兩者之間的關系, 而阻塞非阻塞指的是狀態即某一方。
以前端請求為一個例子,下面的代碼很多人都應該寫過
$.ajax(url).succedd(() => {
......
// to do something
})
同步異步
如果是同步的話, 那么應該是客戶端發起請求后, 一直等到serve處理請求完成后才返回繼續執行后續的邏輯, 這樣客戶端和服務端之間就保持了同步的狀態。
如果是異步的話, 那么應該是客戶端發起請求后, 立即返回, 而請求可能還沒有到達服務端或者請求正在處理, 當然在異步情況下, 客戶端通常會注冊事件來處理請求完成后的情況, 如上面的succeed函數。
阻塞非阻塞
首先需要明白一個概念, Js是單線程, 但是瀏覽器并不是, 事實上你的請求是瀏覽器的另一個線程在跑。
如果是阻塞的話, 那么該線程就會一直等到這個請求完成之后才能被釋放用于其他請求。
如果是非阻塞的話, 那么該線程就可以發起請求后而不用等請求完成繼續做其他事情。
IO是什么?
I/O(英語:Input/Output),即輸入/輸出,通常指數據在內部存儲器和外部存儲器或其他周邊設備之間的輸入和輸出。
異步IO操作
文件讀取的方式是一次性全部讀取,當文件過大的時候,一次性讀取不僅緩慢,而且影響用戶體驗,那么怎么實現分步讀取呢,
這就得使用到異步IO的操作,像水流一樣流出一段取得一段。
具體實現:
我們創建一個文件讀取流,先上代碼
var fs = require("fs");
var data = ""; //聲明一個空字符串來存讀取的數據
var rs = fs.createReadStream("a.txt");
rs.setEncoding("utf-8");
//監聽當有數據流入的時候
rs.on("data",function(chunc){
data += chunc; //將讀取的數據拼接到data上。
console.log("..."); //讀的過程中,我們打印三個點。
});
rs.on("end",function(){
console.log("沒有數據了")
});
我們將 a.txt中的內容增加,以讓讀取時間變長,
代碼中,創建main3.js寫入上面的代碼,使用 reateReadStream創建讀取流對象,在對象上使用on監聽“data”讀取數據的事件,每讀取一段數據,就會觸發這個事件,當讀取完畢, 就會觸發“end”事件。
執行main3.js,我們就可以看到下面打印的結果,從打印的多行"..."中,我們就可以看出,讀取了多次才讀完。
將讀取到的數據,慢慢的寫入 b.txt中
修改mai3.js中的代碼為如下,增加了下面代碼的 4/10/16行,4行表示建立一個寫入流(如果寫入的文件不存在,會自動創建一個文件),10行表示往文件寫入東西,16行表示關閉寫入流。
var fs = require("fs");
var rs = fs.createReadStream("a.txt");
var ws = fs.createWriteStream("b.txt"); //寫入流
rs.setEncoding("utf-8");
//監聽當有數據流入的時候
rs.on("data",function(chunc){
console.log("..."); //讀的過程中,我們打印三個點。
ws.write(chunc,"utf-8"); //向文件寫入東西
});
rs.on("end",function(){
console.log("沒有數據了");
ws.end(); //關閉寫入流
});
這樣我們異步的讀取和寫入文件就實現了
總結
之所以經常會混亂是因為沒有說清楚討論的是哪一部分, 所以同步異步討論的對象時雙方,而阻塞非阻塞討論的市對象自身。
總結
以上是生活随笔為你收集整理的浅谈Node IO操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux 强制卸载硬盘 (Device
- 下一篇: 信息安全主动攻击和被动攻击——就在于对内