學習Node就繞不開異步IO, 異步IO又與事件循環息息相關, 而關於這一塊一直沒有仔細去了解整理過, 恰好最近在作項目的時候, 有了一些思考就記錄了下來, 但願能儘可能將這一塊的知識整理清楚, 若有錯誤, 請指點輕噴~~前端
同步異步 & 阻塞非阻塞ajax
查閱資料的時候, 發現不少人都對異步和非阻塞的概念有點混淆, 其實二者是徹底不一樣的, 同步異步指的是行爲即二者之間的關係 , 而阻塞非阻塞指的是狀態即某一方。瀏覽器
之前端請求爲一個例子,下面的代碼不少人都應該寫過異步
$.ajax(url).succedd(() => { ...... // to do something })
同步異步
函數
若是是同步的話, 那麼應該是客戶端發起請求後, 一直等到serve處理請求完成後才返回繼續執行後續的邏輯, 這樣客戶端和服務端之間就保持了同步的狀態
。學習
若是是異步的話, 那麼應該是客戶端發起請求後, 當即返回, 而請求可能尚未到達服務端或者請求正在處理, 固然在異步狀況下, 客戶端一般會註冊事件來處理請求完成後的狀況, 如上面的succeed函數。ui
阻塞非阻塞
url
首先須要明白一個概念, Js是單線程, 可是瀏覽器並非, 事實上你的請求是瀏覽器的另外一個線程在跑。spa
若是是阻塞的話, 那麼該線程就會一直等到這個請求完成以後才能被釋放用於其餘請求。線程
若是是非阻塞的話, 那麼該線程就能夠發起請求後而不用等請求完成繼續作其餘事情。
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(); //關閉寫入流 });
這樣咱們異步的讀取和寫入文件就實現了
總結
之因此常常會混亂是由於沒有說清楚討論的是哪一部分, 因此同步異步討論的對象時雙方,而阻塞非阻塞討論的市對象自身。