node.js - 使用 module.exports 的 NodeJS 回调

标签 node.js module callback

我从 NodeJS 开始,并尝试了解回调如何与 module.exports 相关。

我有两个 NodeJS 文件。

  1. s1.js 接收输入字段消息并将结果传回。 s1.js 是 通过 module.exports 暴露
  2. 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');

我们将函数分配给变量funcfunc 只是另一个变量,其类型为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/

相关文章:

javascript - 如何创建 JavaScript 回调以了解何时加载图像?

javascript - 带参数的 Nodejs ORM2 回调

python - 为什么 "import"是这样实现的?

c - 绕过 softlockup_threshold

ruby - 如何在 ruby​​ 中引用子模块的 "full path"?

java - 当使用 CursorAdapter 的回调时,调用 initLoader() 仅有效一次

node.js - Npm 安装在 Windows 10 上挂起并失败

node.js - 使用 Azure SDK for Node.js 中的 BlobService.getBlobURL() 生成 Azure 共享访问签名

javascript - Pusher 身份验证套接字 ID 未定义

node.js - Bluebird Promise Warning : . then only accepts functions but was passed