在下面的代码中,val变量值由于异步行为而不断变化并产生意外输出,即在第一个循环的连接查询完成之前,var变量根据第二个循环生成错误输出。处理的最佳方法是什么循环中的查询,避免异步性引起的特性。
var output = [];
for ( var j = 0; j < someArr.length ; j++ ) {
val = someArr[j];//some manipulation of someArr[j]
connection.query( "select id from someTable where someCol = ?",val, function(err, rows, fields) {
if ( err ) {
console.log( err );
} else {
output.push( rows[0].someVal );//push query output to this variable
}
});
}
console.log(output); //应该包含所有查询的输出。
答案 0 :(得分:5)
只需使用闭包来生成临时范围
var output;
for ( var j = 0; j < someArr.length ; j++ ) {
tVal = someArr[i];//some manipulation of someArr[i]
(function(val){
connection.query( "select id from someTable where someCol = ?",val, function(err, rows, fields) {
if ( err ) {
console.log( err );
} else {
output.push( rows[0].someVal );//push query output to this variable
}
});
})(tVal);
}
JavaScript是一种单线程语言,这意味着一次只能执行一个任务。当JavaScript解释器最初执行代码时,它首先默认进入全局执行上下文。从这一点开始每次调用一个函数都会导致创建一个新的执行上下文。
对于每个执行上下文,都有一个与之相关的范围链。范围链包含执行堆栈中每个执行上下文的变量对象。它用于确定变量访问和标识符解析。
匿名函数可帮助我们创建一个“阻止”tVal
值的新范围,因为在执行时,新scope
被添加到包含scope chain
的{{1}}值。
这个新val
是父 scope
的子,执行scope
时,循环继续{{1} }}}但for loop
包含在子 tVal
中,并且不受变体影响。
答案 1 :(得分:2)
最好的&amp;使用循环和标准的标准方法在执行查询中使用 async.eachSeries 。
因此,使用 async.eachSeries ,它将逐个串行执行。一旦foreach完成,你就可以使用回调。
参考:http://caolan.github.io/async/docs.html#eachSeries
var async = require('async');
var output = [];
connection.query('SELECT * FROM tablename LIMIT 10',function(error,results,filelds){
if(error) throw err;
async.eachSeries(results,function(data,callback){ // It will be executed one by one
//Here it will be wait query execute. It will work like synchronous
connection.query('SELECT * FROM tablename where id = 1',function(error,results1,filelds){
if(error) throw err;
output.push(results1[0].id)
callback();
});
}, function(err, results) {
console.log(output); // Output will the value that you have inserted in array, once for loop completed ex . 1,2,3,4,5,6,7,8,9
});
})
答案 2 :(得分:0)
尝试使用“让” 代替“ var” ,这可能有效
var output = [];
for ( let j = 0; j < someArr.length ; j++ ) {
val = someArr[j];//some manipulation of someArr[j]
connection.query( "select id from someTable where someCol = ?",val, function(err, rows, fields) {
if ( err ) {
console.log( err );
} else {
output.push( rows[0].someVal );//push query output to this variable
}
});
}