關於nodejs中的回撥函式理解
阿新 • • 發佈:2019-01-25
Node的三個特點:單執行緒,非阻塞I/O,事件驅動。Node的程式設計思維就是,所有的都是非同步的,因此有了大量的回撥函式。
回撥函式,就是放在另外一個函式(如 parent)的引數列表中,作為引數傳遞給這個 parent,然後在 parent 函式體的某個位置執行。舉個栗子:
var f1 = function(callback)
{
var a = 1,
b = 2,
c = 3;
var s = callback(a,b,c);
return s;
};
var d = f1(function(x,y,z){
return (x+y+z);
});
console.log(d);
首先定義一個f1 函式,它有一個引數 callback,這個 callback 就是回撥函式,名字可以任意取。
在函式體中,定義了三個變數 a,b,c。然後呼叫 callback 函式,最後返回一個值。這裡我們並不知道callback這個回撥函式是幹什麼的,因為沒有定義它的功能,它只是有三個引數。
然後呼叫f1 函式,這時候我們就需要指定 callback 具體要實現什麼了,可以看到,它完成了一個 求和的功能。
再比如,使用ejs模板,完成一個上傳圖片與檢視相簿的功能,我們可能這樣做:
首先定義一個函式完成獲取相簿資料夾的功能:
function getAllAlbums(){
//這裡具體實現功能,最後返回一個資料夾陣列
fs.readdir(...)
}
然後呼叫函式並使用ejs渲染頁面:
var albums = function(req,res,next){
res.render("index",{
"albums" : getAllAlbums()
});
}
但是,這個做法是錯誤的,因為這是傳統的思維!
在node中,你要時刻考慮你的程式碼功能是不是非同步的,非同步的,非同步的。當你要獲取所有的資料夾時,就要涉及到讀檔案,fs.readdir(),而這肯定是非同步的!因此可能你的檔案還沒讀完,頁面就已經被渲染了,這時就會報錯。
所以,正確的做法是,在getAllAlbums中使用callback回撥函式,而在呼叫getAllAlbums時,把讀完檔案後的 資料 當做回撥函式的 引數 來使用:
function getAllAlbums(callback){
fs.readdir("./uploads",function(err,files){
var allAlbums = [];
...
callback(allAlbums);
}
}
var albums = function(req,res,next){
getAllAlbums(function(err,allAlbums){
res.render("index",{
"albums" : allAlbums
});
})
}
這樣便能確保在讀檔案結束後才會渲染頁面,即變非同步為同步了。當然你也可以使用同步讀檔案操作。
ps:這裡的示例程式碼並不完整,只是大概說明非同步的思想,謝謝~