2013-12-18 48 views
1

所以我很困惑函數(err,data)回調是如何工作的,第一個參數總是錯誤處理程序?瞭解函數(錯誤,數據)回調

如果你有類似函數(x,y,z,a,b,c)的話,那麼剩下的參數呢?

fs.readFile中的數據如何從代碼的第一行傳遞到代碼的底部?換句話說,fs.readFile的輸出如何被放入數據參數?

fs.readFile(pathToFile, function (err, **data**) { 
    bufferString = **data**.toString(); 

我可以替換爲函數(X,Y)和功能(X,Y,Z,A,B,C)

但是,只有第二個參數工作功能(ERR,數據)(數據和y),這只是JavaScript回調的語法?

例如,這是工作碼異步讀取文件,並打印出給定的文件的行數:

var fs = require('fs'); 
var pathToFile = process.argv[2]; 
var bufferString, bufferStringSplit; 

function counter(callback) { 
    fs.readFile(pathToFile, function (err, data) { 
    bufferString = data.toString(); 
    bufferStringSplit = bufferString.split('\n'); 
    callback(); 
    }); 
} 

function logMyNumber() { 
    console.log(bufferStringSplit.length-1); 
} 

counter(logMyNumber); 
+2

回調簽名由函數調用確定 - 「readFile」指示2參數回調。這裏沒有魔法。 – Joe

+0

謝謝喬!我想我已經對此進行了深入分析,但它絕對有助於我理解! – enducat

回答

3

回調(這是在這種情況下,readFile方法)的呼叫者決定什麼參數傳遞給回調。你需要聲明你的回調以匹配readFile表示它將傳遞給回調。您可以將所需的任何名稱命名(您使用的名稱無關緊要),但它們將按照readFile決定的順序獲取值。

在這種情況下,fs.readFile()使用您的代碼中的兩個參數調用回調,如callback(err, data)

這裏有一個例子來自Node.js的文檔:

fs.readFile('/etc/passwd', function (err, data) { 
    if (err) throw err; 
    console.log(data); 
}); 
1

回調的參數取決於回調函數被怎麼叫。例如:

var map = function(xs, f) { 
    var result = []; 
    for (var i=0; i<xs.length; i++) { 
    // Here we call the callback function 
    // with the element as context, the element as first param 
    // and the index as second param. 
    // Extra parameters are `undefined` 
    result.push(f.call(xs[i], xs[i], i)); 
    } 
    return result; 
}; 

然後,你使用它像:

var addIdx = function(x,i){ return x+i }; 
map([1,2,3], addIdx); //=> [1,3,5] 
1

容易用一個例子明白......你可以編寫自己的使用一個回調函數的版本,很簡單:

function getTwoStringsAsync(callback) { 
    setTimeout(function() { 
     callback("foo", "bar"); 
    }, 1000); 
} 

這裏,功能getTwoStringsAsync被預先假設「回調」的功能,它意味着簽名(即是字符串兩個參數)。您的方法的使用者可以自由地遵守隱含的簽名。它可以使用這些值中的一個或兩個,或者都不使用。但是,如果它假定有兩個以上的參數,那麼這些參數將顯示爲未定義。

getTwoStringsAsync(function() { console.log("done!"); }); 
getTwoStringsAsync(function(first, second) { console.log("got " + first + ", " + second); }); 
getTwoStringsAsync(function(first, second, third) { console.log(third); }); // "undefined" 

它可以說是一個限制或強度,或弱類型的語言,如Javascript,功能簽名將不會被驗證。強類型語言可能會在上面的第一個或第三個用途中生成編譯器錯誤或警告。

0

當你調用一個函數就可以返回一個的值或者拋出一個錯誤。

所以這個同步代碼「等價物」:

try { 
    var data = functionCall(); 
    //Use data 
} 
catch(err) { 
    console.log(err); 
} 

這是異步回調:

functionCallAsync(function(err, data) { 
    if (err) { 
     console.log(err); 
    } 
    else { 
     //Use data 
    } 

}); 

現在你可以看到爲什麼它是沒有意義的回調使用多個值。事實上,這種模式是有害的。

例如,當您使用生成器時,您只能使用單個返回值。但是,如果一些無知的圖書館作者繼續前進並打破了回調慣例並使用了多個,那麼這是不可能的。

async(function*() { 
    try { 
     //What if `functionCallAsync` was called back with multiple values? 
     var data = yield functionCallAsync(); 
     //Use data 
    } 
    catch(e) { 
     console.log(e); 
    } 
});