1. 程式人生 > >關於nodejs中的回撥函式理解

關於nodejs中的回撥函式理解

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:這裡的示例程式碼並不完整,只是大概說明非同步的思想,謝謝~