我从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");
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的回调。
有什么想法吗?
感谢
列昂
答案 0 :(得分:4)
之前的答案是正确的,但你的问题与nodejs或module.exports没什么关系,但问题是你还没有理解JavaScript(以及PHP和其他语言)中使用的回调的本质。 / p>
您使用的示例实际上使这种差异更难理解。所以这里是一个关于如何理解回调的循序渐进的描述,从简单的语句开始,到代码看起来像你的。
// 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;
换句话说:变量可以指向函数,就像变量可以指向字符串,整数或对象一样。功能是"只是"变量可以指向的类型之一。
将此函数分配给变量不会执行代码!为此,您必须调用变量指向的函数。
答案 1 :(得分:0)
您没有拨打回叫。回调只是普通函数,只是作为函数的参数给出。
您的代码不会调用回调。您正在尝试为回调设置值。固定版本的s1.js:
module.exports.test=function test(msg,result){
result(null, "Hello "+msg);
console.log("Inside s1.js - "+result);
};
这样你就可以调用回调。我们需要传递null
,因为您已将回调函数定义为function(err, result)
。它有两个参数,第一个是err
我们没有遇到错误,所以我们只是传入null
。
答案 2 :(得分:0)
请尝试以下 s1.js 的示例,代码是自解释的,如果您仍需要帮助,请与我们联系。
var defaultValues = module.exports
defaultValues.GetApiURL = function () {
var apiURL = "http://localhost:1000/api/"
return apiURL;
}