使用module.exports的nodejs回调

1 module callback node.js

我从NodeJS开始,试图了解回调如何与module.exports有关。

我有两个NodeJS文件。

  1. s1.js接收输入字段msg并将结果传回。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");
Run Code Online (Sandbox Code Playgroud)

s1.js

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的回调。

有任何想法吗?
谢谢莱昂

Mat*_*ijs 5

前面的答案是正确的,但是您的问题与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)

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

换句话说:变量可以指向函数,就像变量可以指向字符串,整数或对象一样。函数只是变量可以指向的一种类型。

将此函数分配给变量不会执行代码!为此,您必须调用变量指向的函数。