我很新(刚刚开始本周)到Node.js,有一个基本的部分,我无法理解。我有一个辅助函数,它调用MySQL数据库来获取一些信息。然后我使用回调函数将数据返回给调用者,但是当我想在该回调之外使用该数据时,我遇到了麻烦。这是代码:
/** Helper Function **/
function getCompanyId(token, callback) {
var query = db.query('SELECT * FROM companies WHERE token = ?', token, function(err, result) {
var count = Object.keys(result).length;
if(count == 0) {
return;
} else {
callback(null, result[0].api_id);
}
});
}
/*** Function which uses the data from the helper function ***/
api.post('/alert', function(request, response) {
var data = JSON.parse(request.body.data);
var token = data.token;
getCompanyId(token, function(err, result) {
// this works
console.log(result);
});
// the problem is that I need result here so that I can use it else where in this function.
});
正如您所看到的,只要我保持在回调范围内,我就可以访问getCompanyId()的返回值,但我需要在回调之外使用该值。我能够在另一个函数中解决这个问题,只需将所有逻辑都放在回调中,但在这种情况下不起作用。任何关于如何更好地构建这一点的见解都将是最受欢迎的。到目前为止我真的非常喜欢Node.js,但显然我已经学习了很多。
答案 0 :(得分:5)
简短回答 - 如果不违反Node.js的异步特性,就不能这样做。
考虑在回调之外尝试访问result
的后果 - 如果您需要使用该值,并且回调尚未运行,您会怎么做?您不能sleep
并等待设置值 - 这与Node的单线程,事件驱动设计不兼容。在等待回调运行时,整个程序必须停止执行。
依赖于result
的任何代码都应该在getCompanyId
回调中:
api.post('/alert', function(request, response) {
var data = JSON.parse(request.body.data);
var token = data.token;
getCompanyId(token, function(err, result) {
//Any logic that depends on result has to be nested in here
});
});
学习Node.js(和异步编程是一般的)最困难的部分之一是学习异步思考。一开始可能很难,但值得坚持。您可以尝试在程序上进行战斗和编码,但这将不可避免地导致无法维护,错综复杂的代码。
如果您不喜欢多个嵌套回调的想法,可以查看 promises ,它允许您将方法链接在一起而不是嵌套它们。 This article是Q
的一个很好的介绍,是承诺的一种实现。
答案 1 :(得分:2)
如果您担心在回调函数中塞满所有内容,您可以随时命名该函数,将其移出,然后将该函数作为回调函数传递:
getCompanyId(token, doSomethingAfter); // Pass the function in
function doSomethingAfter(err, result) {
// Code here
}
答案 2 :(得分:2)
当我开始将这些视为“火与忘记”的方法时,我的“啊哈”时刻到了。不要查找从方法返回的返回值,因为它们不会返回。调用代码应该继续,或者只是结束。是的,感觉很奇怪。
正如@joews所说,你必须根据回调中的值放置所有内容。
这通常需要您传递额外的参数。例如,如果您正在执行典型的HTTP请求/响应,请计划沿着回调链向每个步骤发送响应。最终回调将(希望)在响应中设置数据,或设置错误代码,然后将其发送回用户。
答案 3 :(得分:1)
如果你想避免回调气味,你需要使用Node的Event Emitter Class,如下所示:
在文件顶部需要事件模块 -
var emitter = require('events').EventEmitter();
然后在你的回调中:
api.post('/alert', function(request, response) {
var data = JSON.parse(request.body.data);
var token = data.token;
getCompanyId(token, function(err, result) {
// this works
console.log(result);
emitter.emit('company:id:returned', result);
});
// the problem is that I need result here so that I can use it else where in this function.
});
then after your function you can use the on method anywhere like so:
getCompanyId(token, function(err, result) {
// this works
console.log(result);
emitter.emit('company:id:returned', result);
});
// the problem is that I need result here so that I can use it else where in this function.
emitter.on('company:id:returned', function(results) {
// do what you need with results
});
请注意为您的活动设置好的命名空间约定,这样您就不会弄乱事件,也应该观察您附加的听众数量,这里有一个很好的参考链接: