我从NodeJS开始,试图了解回调如何与module.exports有关。
我有两个NodeJS文件。
var s1=require('./s1.js');
var r1;
s1.test("Leon", function(err, result) {
if (err){console.log("Error occurred "+err);}
console.log("Callback after s1.test execution "+result);
r1=result;
}
);
console.log("result "+r1);
console.log("end");
Run Code Online (Sandbox Code Playgroud)
module.exports.test=function test(msg,result){
result="Hello "+msg;
console.log("Inside s1.js - "+result);
};
Run Code Online (Sandbox Code Playgroud)
当我执行start.js时,结果如下
Inside s1.js - Hello Leon
result undefined
end
Run Code Online (Sandbox Code Playgroud)
如预期的那样,结果尚未定义,因为s1.test的回调尚未完成。
我不明白的是为什么从未实现s1.test的回调。
有任何想法吗?
谢谢莱昂
前面的答案是正确的,但是您的问题与nodejs或module.exports无关,但问题是您还不了解JavaScript(以及PHP和其他语言)中使用的回调的性质。
您使用的示例实际上使这种区别更难以理解。因此,这是有关如何理解回调的分步说明,从简单的语句开始,以与您的代码相似的代码结束。
// Create some object
var fooBar = { foo: 'foo object'};
// Add a bar function to that object
fooBar.bar = function (param1, param2) {
console.log("Inside bar function: " + param1);
};
Run Code Online (Sandbox Code Playgroud)
创建对象并添加了一个函数后,运行该代码不会记录任何内容,但是永远不会调用该函数。
为此,我们需要添加对该函数的调用:
fooBar.bar('test 1');
Run Code Online (Sandbox Code Playgroud)
现在我们得到输出:
Inside bar function: test 1
Run Code Online (Sandbox Code Playgroud)
或者我们可以两次调用该函数:
fooBar.bar('test 1');
fooBar.bar('test 2');
Run Code Online (Sandbox Code Playgroud)
现在我们得到输出:
Inside bar function: test 1
Inside bar function: test 2
Run Code Online (Sandbox Code Playgroud)
下一步是创建一个函数,该函数类似于您在调用中用作第二个参数的函数s1.test()。但是,我们没有将其分配给该参数,而是将其分配给了另一个变量。
// Create some object
var fooBar = { foo: 'foo object'};
// Add a bar function to that object
fooBar.bar = function (param1, param2) {
console.log("Inside bar function: " + param1);
};
// Create assign a function to a variable
var func = function (err, result) {
console.log("Inside func function, call using: " + err + " and " + result);
}
fooBar.bar('test 1');
fooBar.bar('test 2');
Run Code Online (Sandbox Code Playgroud)
她我们将函数分配给变量func。func只是另一个变量,类型为function。JavaScript中的回调只是类型为的变量function。要查看此运行:
console.log(typeof func);
Run Code Online (Sandbox Code Playgroud)
输出为:
function
Run Code Online (Sandbox Code Playgroud)
输出不变!将新功能定义并分配给变量作为回调不会运行代码!您需要调用函数来运行代码。因此,我们开始调用该函数并将最后两行更改为四行:
func('outside', 'call 1');
fooBar.bar('test 1');
fooBar.bar('test 2');
func('outside', 'call 2');
Run Code Online (Sandbox Code Playgroud)
现在的输出是:
Inside func function, call using: outside and call 1
Inside bar function: test 1
Inside bar function: test 2
Inside func function, call using: outside and call 2
Run Code Online (Sandbox Code Playgroud)
现在更接近您的示例,我们将func变量作为第二个参数传递给fooBar.bar()函数:
func('outside', 'call 1');
fooBar.bar('test 1', func);
fooBar.bar('test 2', func);
func('outside', 'call 2');
Run Code Online (Sandbox Code Playgroud)
输出仍然是:
Inside func function, call using: outside and call 1
Inside bar function: test 1
Inside bar function: test 2
Inside func function, call using: outside and call 2
Run Code Online (Sandbox Code Playgroud)
为什么?因为fooBar.bar()函数内的代码对第二个参数不执行任何操作。因此,我们将此功能更改为:
// Add a bar function to that object
fooBar.bar = function (param1, param2) {
console.log("Inside bar function: " + param1);
console.log("The type of param 2 is: " + typeof param2);
};
Run Code Online (Sandbox Code Playgroud)
结果输出是这样的:
Inside func function, call using: outside and call 1
Inside bar function: test 1
The type of param 2 is: function
Inside bar function: test 2
The type of param 2 is: function
Inside func function, call using: outside and call 2
Run Code Online (Sandbox Code Playgroud)
此输出显示的param2是函数本身的值,而不是输出结果!要运行代码,我们要做的就是将其param2用作函数,甚至可以多次调用该函数:
// Add a bar function to that object
fooBar.bar = function (param1, param2) {
param2("inside bar 1", param1);
console.log("Inside bar function: " + param1);
param2("inside bar 2", param1);
};
Run Code Online (Sandbox Code Playgroud)
结果是:
Inside func function, call using: outside and call 1
Inside func function, call using: inside bar 1 and test 1
Inside bar function: test 1
Inside func function, call using: inside bar 2 and test 1
Inside func function, call using: inside bar 1 and test 2
Inside bar function: test 2
Inside func function, call using: inside bar 2 and test 2
Inside func function, call using: outside and call 2
Run Code Online (Sandbox Code Playgroud)
现在终于可以创建类似于start.js的代码了。除了func使用示例中的匿名函数外,我们没有为函数创建变量。完整的代码变为:
// Create some object
var fooBar = { foo: 'foo object'};
// Add a bar function to that object
fooBar.bar = function (param1, param2) {
param2("inside bar 1", param1);
console.log("Inside bar function: " + param1);
param2("inside bar 2", param1);
};
// fooBar.bar('test 2', func);
// Use anonymous function instead of func
fooBar.bar('test 3', function (err, result) {
console.log("Inside anonymous function, call using: " + err + " and " + result);
}
);
Run Code Online (Sandbox Code Playgroud)
现在的输出变为:
Inside anonymous function, call using: inside bar 1 and test 3
Inside bar function: test 3
Inside anonymous function, call using: inside bar 2 and test 3
Run Code Online (Sandbox Code Playgroud)
我们可以fooBar.bar使用另一个函数添加另一个调用:
fooBar.bar('test 4', function (err, result) {
console.log("Inside another anonymous function, call using: " + err + " and " + result);
}
);
Run Code Online (Sandbox Code Playgroud)
输出:
Inside anonymous function, call using: inside bar 1 and test 3
Inside bar function: test 3
Inside anonymous function, call using: inside bar 2 and test 3
Inside another anonymous function, call using: inside bar 1 and test 4
Inside bar function: test 4
Inside another anonymous function, call using: inside bar 2 and test 4
Run Code Online (Sandbox Code Playgroud)
我希望这些示例可以阐明为什么永远不会调用start.js中的匿名函数。
最后一个有趣的注意事项:创建匿名函数并将其分配给变量与仅使用javaScript创建函数之间有区别吗?介于:
// Create assign a function to a variable
var func = function (err, result) {
console.log("Inside func function, call using: " + err + " and " + result);
}
Run Code Online (Sandbox Code Playgroud)
和:
function func (err, result) {
console.log("Inside func function, call using: " + err + " and " + result);
}
Run Code Online (Sandbox Code Playgroud)
答案是不!两者都func在全局堆栈中创建一个名称相同的指针,以指向同一函数。您甚至可以使用其他名称创建全局函数,并使func变量指向该函数。此示例与之前的示例一样有效:
function funcy (err, result) {
console.log("Inside func function, call using: " + err + " and " + result);
}
var func = funcy;
Run Code Online (Sandbox Code Playgroud)
换句话说:变量可以指向函数,就像变量可以指向字符串,整数或对象一样。函数只是变量可以指向的一种类型。
将此函数分配给变量不会执行代码!为此,您必须调用变量指向的函数。