我知道node的事件驱动/非阻塞的东西,我已经使用它大约2年了…最近我遇到了这个问题,我不能解决它,甚至强制关闭…
我要求数据库为一个简单的结果:'SELECT 1+1作为结果'
(...) // previous code
var dbRows1 = {}; // empty object to hold rows
var dbRows2 = {}; // idem
var mysql = require( 'mysql' );
var db = mysql.createConnection( dbInfo ); // dbInfo has connction data
var test = function( a ) { dbRows2 = a };
db.connect(
function( err )
{
if (err) throw err.stack;
console.log( 'TID ->', db.threadId)
});
db.query (
'SELECT 1+1 AS XXX',
function( err, rows, fields )
{
console.log( 'rows ->', rows ); // works ok
dbRows1 = rows; // don't work because rows is still empty
test( rows ); // !!!should work but dbRows2 is empty at program end!!!
});
(...) // more code
console.log( dbRows2 );
最后一行为dbRows2({})打印一个空对象…
为什么console.log()工作,我的test()函数不工作?
您的测试函数正在工作,问题是,在您的最后一个console.log
语句执行时,测试函数尚未执行。这是因为.connect
和.query
都是异步的。
程序流程看起来像这样:
- 连接被调用并排队
- 查询被调用并排队
- console.log(dbRows2)被称为
- (时间的流逝…)
- 连接成功并回呼
- (时间的流逝…)
- 查询成功,回调
- 测试被称为分配行给dbRows2
您可以通过在每个操作之前和回调内部的代码中放置一些策略日志来验证这种行为。如果你这样做了,你会在控制台中看到这样的内容:
about to call connect
about to call query
logging dbRows2
connect succeeded
query succeeded
about to call test
在不知道代码的确切结构的情况下,下面提供了一个粗略的示例,说明如何构建逻辑以确保仅在查询完成后调用依赖于查询完成的代码:
db.query (
'SELECT 1+1 AS XXX',
function( err, rows, fields )
{
console.log( 'rows ->', rows ); // works ok
dbRows1 = rows; // don't work because rows is still empty
test( rows ); // !!!should work but dbRows2 is empty at program end!!!
// Call doStuffThatDependsOnQuery here
doStuffThatDependsOnQuery();
});
(...) // more code that doesn't depend on db.query(...)
function doStuffThatDependsOnQuery() {
console.log( dbRows2 );
}