我在Node.js中从回调函数返回一个值时遇到小问题,我将尽可能简单地解释我的情况。考虑我有一个片段,它接受URL并点击该url并给出输出:
urllib.request(urlToCall, { wd: 'nodejs' }, function (err, data, response) {
var statusCode = response.statusCode;
finalData = getResponseJson(statusCode, data.toString());
});
我尝试将其包装在函数中并返回如下值:
function doCall(urlToCall) {
urllib.request(urlToCall, { wd: 'nodejs' }, function (err, data, response) {
var statusCode = response.statusCode;
finalData = getResponseJson(statusCode, data.toString());
return finalData;
});
}
因为在我的Node.js代码中,我有很多if-else
语句,其中urlToCall
的值将被确定,如下所示:
if(//somecondition) {
urlToCall = //Url1;
} else if(//someother condition) {
urlToCall = //Url2;
} else {
urlToCall = //Url3;
}
问题是urllib.request
中的所有语句都将保持不变,除了urlToCall
的值。所以我肯定需要将这些公共代码放在函数中。我尝试了同样的方法,但在doCall
中我总是会回复undefined
。我试过这样:
response = doCall(urlToCall);
console.log(response) //Prints undefined
但是,如果我在doCall()
内打印值,它会完美打印,但它将始终返回undefined
。根据我的研究,我发现我们无法从回调函数返回值! (是真的吗?)如果是的话,任何人都可以建议我如何处理这种情况,因为我想防止每个if-else
块中的重复代码。
答案 0 :(得分:107)
其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);
});
}
现在:
var urlToCall = "http://myUrlToCall";
doCall(urlToCall, function(response){
// Here you have access to your variable
console.log(response);
})
@Rodrigo,在评论中发布了good resource。阅读节点中的回调以及它们的工作原理。请记住,它是异步代码。
答案 1 :(得分:13)
我在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;
});
}
行callback(finalData);
调用需要从异步函数获得的值的函数。但请注意,return语句用于指示函数在此处结束,但它并不意味着该值将返回给调用者(调用者已经移动了。)
答案 2 :(得分:2)
如果你想要的是让代码工作而不需要修改太多。你可以试试这个摆脱回调的解决方案,保持相同的代码工作流程:
鉴于您使用的是Node.js,您可以使用co和co-request来实现相同的目标,而不会出现回调问题。
基本上,你可以这样做:
var response = yield doCall(urlToCall); // "yield" garuantees the callback finished.
console.log(response) // The response will not be undefined anymore.
然后,
{{1}}
通过这样做,我们等到回调函数完成,然后从中获取值。不知何故,它解决了你的问题。
答案 3 :(得分:1)
node.js的示例代码 - 同步函数的异步函数:
configure