NodeJS回调范围问题
NodeJS Callback Scoping Issue
我是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,但显然我有很多东西要学
简短的回答-如果不违反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(异步编程是通用的)最困难的部分之一是学习异步思考。一开始可能很困难,但值得坚持。您可以尝试按程序进行战斗和编码,但这将不可避免地导致无法维护、复杂的代码。
如果您不喜欢多个嵌套回调的想法,可以查看promise,它允许您将方法链接在一起,而不是嵌套它们。本文很好地介绍了promise的一个实现Q
。
如果你担心回调函数中的所有内容都被塞满了,你总是可以命名函数,将其移出,然后将函数作为回调传递:
getCompanyId(token, doSomethingAfter); // Pass the function in
function doSomethingAfter(err, result) {
// Code here
}
我的"啊哈"时刻到来了,我开始把这些看作是"fire-and-forget"方法。不要寻找从方法返回的返回值,因为它们不会返回调用代码应该继续,或者结束。是的,感觉很奇怪。
正如@joews所说,您必须将取决于该值的所有内容放入回调中。
这通常需要您传递一个额外的参数。例如,如果您正在执行典型的HTTP请求/响应,请计划在回调链上的每一步向下发送响应。最后的回调将(希望)在响应中设置数据,或者设置错误代码,然后将其发送回用户。
如果你想避免回调气味,你需要使用Node的事件发射器类,比如:
文件顶部需要事件模块-
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
});
只要小心为您的事件设置好的名称空间约定,这样您就不会对事件感到混乱,而且您还应该注意连接的侦听器的数量,这里有一个很好的链接供参考:
http://www.sitepoint.com/nodejs-events-and-eventemitter/
- setInterval游戏循环的范围问题
- Javascript innerHTML超出范围的问题
- AngularJs避免范围界定问题
- firefox中的Javascript事件范围问题
- AngularJS指令范围约束问题重复出现
- jQuery“this”范围问题
- 可以't在quizz页面范围问题上用最终分数更新变量
- JavaScript 函数变量范围问题
- 奇怪的可变范围问题
- JavaScript 中变量范围的问题
- 主干.js(具有 Require.js)变量/范围访问问题
- 递归承诺调用 - 内存范围变量问题
- JQuery 范围滑块步进更改问题
- AngularJS中的范围问题
- 如何在 JavaScript for D3.js 中解决这样的范围问题
- 我可以设置这个吗'某事'在该服务中动态创建的嵌套对象中的服务?(可能是范围问题)
- Highcharts列范围工具提示问题
- 在函数中提示未定义返回.(问题)范围
- 访问Javascript's变量:涉及Javascript, JQuery和PHP/MySQL的问题&范围
- JavaScript 闭包问题..范围