前言
說到回調函數,可能大家都會想到異步編程的首選解決方案 9102,更多的異步編程方案層出不窮,典型的代表就是 promise ,async await 不扯遠了,回到NodeJs
。
Node.js 異步編程的直接體現就是回調,回調函數在完成任務後就會被調用,Node 使用了大量的回調函數,Node 所有 API 都支持回調函數。
例如:我們可以一邊讀取文件,一邊執行其他命令,在文件讀取完成後,我們將文件內容作爲回調函數的參數返回,這樣在執行代碼時就沒有阻塞或等待文件 I/O 操作。這就大大提高了 Node.js 的性能,可以處理大量的併發請求
。
這裏邊有一個關鍵詞 I/O
, 說到 I/O
很多童鞋可能不太理解什麼是 I/O
,I/O
其實是 輸入/輸出(Input/Output)
,可自行百度百科一下,從這裏再說到同步I/O,異步I/O 可能大家就能明白了。
- 同步
I/O
阻塞 , 同步輸入輸出 - 異步
I/O
不阻塞, 異步輸入輸出
如果有童鞋不太理解同步/異步這個問題,建議自行學習一下哈 ~
迴歸正題,回調函數
一般,回調函數作爲函數的最後一個參數出現,例如:
function foo(name, age, callback) { }
// callback 就是回調函數
我們來通過同步I/O,異步I/O實例來實踐一下:
創建一個阻塞的同步I/O實例
input.txt 內容: hello 回調函數
這裏的 fs 是nodeJs 的文件系統模塊兒 fs.readFileSync
是同步讀取文件內容,fs 後邊會講到。
// callback.js 內容
var fs = require("fs");
var data = fs.readFileSync('input.txt');
console.log(data.toString());
console.log("程序運行結束!");
這裏涉及到如何運行 nodeJs 文件,我們簡單說一下,就是在項目工程根目錄創建一個xx.js
文件,然後在根目錄運行 node xx.js
文件即可,例子:
目錄: PS C:\HiSen\myWorkDemo\node_demo>
運行命令:node callback.js
callback.js // 如上代碼內容
input.txt // 如上內容
運行命令
PS C:\HiSen\myWorkDemo\node_demo> node callback.js
hello 回調函數
程序運行完畢
PS C:\HiSen\myWorkDemo\node_demo>
很清楚的可以看到,我們打印了
hello 回調函數
程序運行完畢
按照Js單線程,自上而下執行,依次打印結果。
那我們來一個非堵塞異步I/O實例
同樣的結構,我們只用修改一下 callback.js
的文件讀取方式,如下:
fs.readFile 異步讀取文件內容
, 回調函數有兩個參數
1,error 錯誤,異常
2,成功回調結果
var fs = require("fs");
fs.readFile("input.txt", function (err, res) {
console.log(res.toString())
});
// console.log(data.toString()) // 同步試驗
console.log("程序運行完畢")
同樣運行程序 node callback.js
, 發現先打印程序運行完畢,再打印 hello 回調函數 。
PS C:\HiSen\myWorkDemo\node_demo> node callback.js
程序運行完畢
hello 回調函數
PS C:\HiSen\myWorkDemo\node_demo>
結論:
- 通過同步I/O,異步I/O來認識了回調函數和實踐
- 同步I/O,堵塞
- 異步I/O,不堵塞,大大提高了程序的性能