我从 NodeJS 开始,并尝试了解回调如何与 module.exports 相关。
我有两个 NodeJS 文件。
- s1.js 接收输入字段消息并将结果传回。 s1.js 是 通过 module.exports 暴露
- start.js 包含 s1.js(通过 require)并接收我想在程序中使用的结果
start.js
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");
s1.js
module.exports.test=function test(msg,result){
result="Hello "+msg;
console.log("Inside s1.js - "+result);
};
当我执行 start.js 时,结果如下
Inside s1.js - Hello Leon
result undefined
end
正如预期的那样,结果未定义,因为 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);
};
运行此代码不会在创建对象并添加一个函数时记录任何内容,但该函数永远不会被调用。
为此,我们需要添加对该函数的调用:
fooBar.bar('test 1');
现在我们得到输出:
Inside bar function: test 1
或者我们可以调用该函数两次:
fooBar.bar('test 1');
fooBar.bar('test 2');
现在我们得到输出:
Inside bar function: test 1
Inside bar function: test 2
下一步是创建一个函数,类似于您在调用 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');
我们将函数分配给变量func
。 func
只是另一个变量,其类型为function
。 JavaScript 中的回调只是一个function
类型的变量。要查看此运行:
console.log(typeof func);
输出为:
function
输出没有改变! 定义这个新函数并将其分配给变量作为回调不会运行代码!您需要调用该函数来运行代码。所以我们开始调用该函数并将最后两行更改为四行:
func('outside', 'call 1');
fooBar.bar('test 1');
fooBar.bar('test 2');
func('outside', 'call 2');
现在的输出是:
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
现在为了更接近您的示例,我们将 func
变量作为第二个参数传递给 fooBar.bar()
函数:
func('outside', 'call 1');
fooBar.bar('test 1', func);
fooBar.bar('test 2', func);
func('outside', 'call 2');
输出仍然是:
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
为什么?因为 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);
};
结果输出是这样的::
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
此输出显示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);
};
结果是:
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
现在终于可以创建类似于 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);
}
);
输出现在变为:
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
我们可以使用另一个函数添加对 fooBar.bar
的另一个调用:
fooBar.bar('test 4', function (err, result) {
console.log("Inside another anonymous function, call using: " + err + " and " + result);
}
);
输出:
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
我希望这些示例能够阐明为什么 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);
}
和:
function func (err, result) {
console.log("Inside func function, call using: " + err + " and " + result);
}
答案是否定的!两者都在全局堆栈中创建一个名为 func
的指针来指向同一个函数。您甚至可以使用其他名称创建全局函数,并让 func
变量指向它。此示例与之前使用的示例一样有效:
function funcy (err, result) {
console.log("Inside func function, call using: " + err + " and " + result);
}
var func = funcy;
换句话说:变量可以指向函数,就像变量可以指向字符串、整数或对象一样。函数“只是”变量可以指向的类型之一。
将此函数分配给变量不会执行代码!为此,您必须调用变量指向的函数。
关于node.js - 使用 module.exports 的 NodeJS 回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36662111/