在下面的代码中,由于异步行为, 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);//应该包含所有查询的输出。
只需使用闭包来生成临时作用域
var output;
for ( var j = 0; j < someArr.length ; j++ ) {
tVal = someArr[j];//some manipulation of someArr[j]
(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);
}
Theory
执行上下文
JavaScript 是一种单线程语言,这意味着一次只能执行一个任务。当 JavaScript 解释器最初执行代码时,默认情况下它首先进入全局执行上下文。从此时起,每次调用函数都将创建一个新的执行上下文。
范围链
对于每个执行上下文,都有一个与其耦合的作用域链。作用域链包含执行堆栈中每个执行上下文的变量对象。它用于确定变量访问和标识符解析。
解释
匿名函数帮助我们创建一个新的作用域“阻止”tVal
因为什么时候执行一个新的scope
被添加到scope chain
含有val
价值。
这个新的scope
is a child of the parent scope
其中for loop
被执行,当循环继续时tVal
改变但是val
包含在child scope
并且不受变化的影响。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)