標籤:操作 nod 命令 方法 cti 資料 實踐 非同步編程 特定
Node.js 非同步編程的直接體現就是回調。
那什麼是回調呢?回調指的是將一個函數作為參數傳遞給另一個函數,並且通常在第一個函數完成後被調用。需要指明的是,回呼函數不是由該函數的實現方直接調用,而是在特定的事件或條件發生時由另外的一方調用的,用於對該事件或條件進行響應。回呼函數在完成任務後就會被調用,Node 使用了大量的回呼函數,Node 所有 API 都支援回呼函數。例如,我們可以一邊讀取檔案,一邊執行其他命令,在檔案讀取完成後,我們將檔案內容作為回呼函數的參數返回。這樣在執行代碼時就沒有阻塞或等待檔案 I/O 操作。這就大大提高了 Node.js 的效能,可以處理大量的並發請求。
雖然非同步編程依託於回調來實現,但不能說使用了回調後程式就非同步化了。
在開始下面的內容之前,我們需要先瞭解幾個概念:
什麼是阻塞:
所謂阻塞,即每次執行一個操作,在一個操作完成之前,代碼的執行會被暫停,無法繼續下一個操作。
什麼是非阻塞:
所謂非阻塞,指的是基於回調、允許指令碼並存執行操作的方法,操作結果會在事件發生時由回調來處理,從而無需等待某個操作的結果繼續下一步。
舉個栗子解釋一下阻塞和非阻塞的區別:
你在家裡做飯,結果發現家裡沒醬油了,所以你就停下手上的活跑去商店買醬油。結果店員告訴你說現在沒醬油了,採購員正在外面採購,需要等一下才回來。這時候你就有兩個選擇:一是繼續在商店裡等採購員回來,拿到醬油回家繼續做菜;二是先回家忙其他的活,等一下再回來買醬油。
第一個選擇其實就是阻塞的做法,需要等到醬油買到之後才繼續其他的事。第二個選擇就是非阻塞的做法,先去做其他的事,等到合適的時候再去買醬油。(當然,這栗子有點不靠譜。希望大家能看懂我的意思。)
實踐出真知,講完基礎的知識點,那就開始敲一下代碼吧。擼起袖子就是幹。
現在這裡過一下下面執行個體會使用到的API:
讀取檔案(同步操作):fs.readFileSync(file[, options])
讀取檔案(非同步作業):fs.readFile(file[, options], callback)
阻塞代碼執行個體
先建立一個txt檔案,比如demo2.txt。然後在裡面隨便敲一點東西,比如:
****** this is my second demo! ******
然後再在同個目錄下建立一個js指令碼,我把它取名為demo2.js,代碼如下:
//引入fs(filesystem)模組,在指令碼使用var fs = require("fs");//同步讀取檔案var data = fs.readFileSync(‘demo2.txt‘);//列印資料console.log(data.toString());console.log("------ 程式執行結束! ------");
最後就可以使用node指令運行我們的代碼了!是不是很心急,那就來看看吧。
//node指令node demo2.js
cmd運行效果:
可以看到,js指令碼讀取完檔案並輸出檔案內容之後,才會繼續執行下面的console.log("------ 程式執行結束! ------")。由於讀取檔案和輸出內容需要時間,在讀取和輸出的過程中指令碼並不會先去執行其他代碼,而是要等到讀取並輸出檔案內容完成之後才會接著去進行下一步操作。這就是所謂的(同步)阻塞。
非阻塞代碼執行個體
demo2.txt仍跟之前的一樣。我們只要修改demo.js代碼就行,具體代碼如下:
//引入fs(filesystem)模組,在指令碼使用
var fs = require("fs");//非同步讀取檔案fs.readFile(‘demo2.txt‘, function (err, data) { if (err) return console.error(err); //若讀取失敗,則報出錯誤 console.log(data.toString()); //讀取成功則輸出檔案內容});console.log("程式執行結束!");
來看看運行效果:
可以看到,由於使用了非同步讀取操作,所以在讀取檔案的時候,指令碼會繼續執行下面的代碼,也就是說,不管檔案是否讀取並輸出完畢,指令碼都會往下執行。所以就會看到先執行完console.log("------ 程式執行結束! ------")之後才看到輸出"****** this is my second demo! ******"。這就是所謂的(非同步)非阻塞。
以上兩個執行個體我們瞭解了阻塞與非阻塞調用的不同。第一個執行個體在檔案讀取完後才執行完程式。 第二個執行個體我們不需要等待檔案讀取完,這樣就可以在讀取檔案時同時執行接下來的代碼,大大提高了程式的效能。
因此,阻塞是按順序執行的,而非阻塞是不需要按順序的,所以如果需要處理回呼函數的參數,我們就需要寫在回呼函數內。
你們看懂了嗎?反正我是懂了(~ ̄▽ ̄)~
node.js學習筆記(二)——回呼函數