徹底理解 Node.js 中的回調(Callback)函數
究竟什麼是回調函數(Callback),網上有許許多多的文章,大部分看得人云里霧外,這些文章大概分成兩類,第一類堆砌了太多的術語,基本上不明白朮語就沒法看,另一類反過來,不講術語,完全是舉一些脫離編程的生活化例子來類比,看的人更加暈頭轉向。
作為JS的核心,回調函數和非同步執行是緊密相關的,不跨過這個門檻,很多回調代碼能把人看暈!
引用stack overflow 上大神的描述 其實callback 很簡單也很純粹:
A "callback" is any function that is called by another function which takes the first function as a parameter. (在一個函數中調用另外一個函數就是callback)
以下是一個最簡單的例子:
function a() {
return 1
}
function b(aa) {
return 2 + aa
}
//調用:
var c=0
c = b(a()) //A是個函數,但它又作為一個參數在B函數中被調用
console.log(c) //結果顯示3
以上例子極易理解,下面再引入另一個概念:非同步
看以下代碼:
var a = 0
function bb(x) {
console.log(x)
}
function timer(time) {
setTimeout(function () {
a=6
}, time);
}
//調用:
console.log(a)
timer(3000)
bb(a)
以上代碼很簡單,我們需要的邏輯是,全局變數a初值為0,然後過3秒後,讓它為6,然後再列印出來,看上去,上面的代碼沒有問題,理論上符合我們的邏輯需求,但卻發現結果是這樣:
0
0
咋回事?
因為JS是一種非同步執行語言,儘管timer函數內讓a=6了,但是JS不會死等時間結束再跳出函數,而是馬上就會執行下一步語句(即調用bb函數),但這時候3秒鐘根本就沒結束,a還沒有被重新賦值,所以列印出來還是為0。
用回調函數可以解決這個問題:
var a = 0
function bb(x) {
console.log(x)
}
function timer(time, callback) {
setTimeout(function () {
a = 6
callback(a);
}, time);
}
//調用:
console.log(a)
timer(3000,bb)
這次,在timer函數中添加了一個關鍵字callback,意思就是說此處不是一個普通的參數,而是一個函數名,打起精神,關鍵的地方來了:
一般而言,函數的形參是指由外往內向函數體傳遞變數的入口,但此處加了callback後則完全相反,它是指函數體在完成某種使命後調用外部函數的出口!這時候應該明白什麼叫"回調"了吧,也就是回頭調用外部函數的意思。
在本例中,當3秒鐘到了後,首先a=6,然後通過關鍵字callback(a)調用了函數bb(x),結果顯示:
0
6
這個邏輯,符合我們的需求。
在寫法上,也可以不需要定義函數bb, 直接在調用timer的時候寫成function形式,把調用部分改成這樣也可以,效果完全一樣:
console.log(a)
timer(3000, function (x) {
console.log(x)
})
這種寫法函數名都不需要了(術語稱為"匿名函數"),在nodejs代碼中更為常見也更好理解,翻譯成自然語言就是:定時3秒,完成後再回頭調用function(x)裡面的內容。
nodejs編程中大量使用了非同步編程技術,這是為了高效使用硬體,同時也可以不造成同步阻塞。其實nodejs在底層還是通過多線程技術實現的非同步操作,但普通用戶並不需要深究它的實現方法,我們只要做好我們的非同步處理即可。
打開今日頭條,查看更多圖片TAG:程序員小新人學習 |