2013-12-18 71 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); 
    } 
});