从Node.js中的回调函数返回一个值

Pra*_*mha 72 javascript node.js

我在Node.js中从回调函数返回一个值时遇到小麻烦,我会尽量解释我的情况.考虑我有一个片段,它接受URL并点击该url并给出输出:

urllib.request(urlToCall, { wd: 'nodejs' }, function (err, data, response) {                              
    var statusCode = response.statusCode;
    finalData = getResponseJson(statusCode, data.toString());
});
Run Code Online (Sandbox Code Playgroud)

我试图将它包装在一个函数中并返回一个这样的值:

function doCall(urlToCall) {
urllib.request(urlToCall, { wd: 'nodejs' }, function (err, data, response) {                              
    var statusCode = response.statusCode;
    finalData = getResponseJson(statusCode, data.toString());
    return finalData;
});
}
Run Code Online (Sandbox Code Playgroud)

因为在我的Node.js代码中,我有很多if-else声明urlToCall将决定其值,如下所示:

if(//somecondition) {
   urlToCall = //Url1;
} else if(//someother condition) {
   urlToCall = //Url2;
} else {
   urlToCall = //Url3;
}
Run Code Online (Sandbox Code Playgroud)

事情是urllib.request,除了值之外,一个遗嘱中的所有陈述都保持不变urlToCall.所以我肯定需要将这些公共代码放在函数中.我尝试了同样但doCall总是会回报我undefined.我试过这样的:

response = doCall(urlToCall);
console.log(response) //Prints undefined
Run Code Online (Sandbox Code Playgroud)

但是,如果我在doCall()其中打印值,它打印完美,但它将永远返回undefined.根据我的研究,我发现我们无法从回调函数返回值!(是真的吗?)如果是的话,任何人都可以建议我如何处理这种情况,因为我想防止每个if-else块中的重复代码.

alu*_*sen 117

undefined原因,console.log(response)运行前doCall(urlToCall);完成.您还必须传入一个回调函数,该函数在您的请求完成时运行.

首先,你的功能.传递回调:

function doCall(urlToCall, callback) {
    urllib.request(urlToCall, { wd: 'nodejs' }, function (err, data, response) {                              
        var statusCode = response.statusCode;
        finalData = getResponseJson(statusCode, data.toString());
        return callback(finalData);
    });
}
Run Code Online (Sandbox Code Playgroud)

现在:

var urlToCall = "http://myUrlToCall";
doCall(urlToCall, function(response){
    // Here you have access to your variable
    console.log(response);
})
Run Code Online (Sandbox Code Playgroud)

@Rodrigo,在评论中发布了一个很好的资源.阅读节点中的回调及其工作原理.请记住,它是异步代码.

  • 这很好用.但我有一个问题.在调用doCall函数的情况下.我怎样才能返回响应变量?例如,我想在函数外获取该变量? (11认同)
  • @Romeo同样的问题在这里! (3认同)
  • 你好,抱歉,如果我误解了,但这有什么不同吗?urllib 响应现在只是停留在它之外的另一个函数的范围内。您现在不能在 doCall 之外的任何地方使用响应对象吗? (2认同)

Hec*_*rea 14

我在Node.js中从回调函数返回一个值时遇到了一些麻烦

这不是一个"小麻烦",实际上不可能从异步函数中"返回"传统意义上的值.

由于您无法"返回值",因此必须调用需要该值的函数.@display_name已经回答了你的问题,但我只想指出doCall中的返回不是以传统方式返回值.您可以编写doCall,如下所示:

function doCall(urlToCall, callback) {
    urllib.request(urlToCall, { wd: 'nodejs' }, function (err, data, response) {                              
        var statusCode = response.statusCode;
        finalData = getResponseJson(statusCode, data.toString());
        // call the function that needs the value
        callback(finalData);
        // we are done
        return;
    });
}
Run Code Online (Sandbox Code Playgroud)

Line callback(finalData);是调用需要从async函数获得的值的函数.但请注意,return语句用于指示函数在此处结束,但这并不意味着该值将返回给调用者(调用者已经移动了.)


Daw*_*ski 5

node.js 的示例代码 - 异步函数到同步函数:

var deasync = require('deasync');

function syncFunc()
{
    var ret = null;
    asyncFunc(function(err, result){
        ret = {err : err, result : result}
    });

    while((ret == null))
    {
         deasync.runLoopOnce();
    }

    return (ret.err || ret.result);
}
Run Code Online (Sandbox Code Playgroud)