我的代码:
function listshops(callback)
{
client.connection.query('select * from shop',function(err,rows){
if(rows.length>0)
{
for(var i=0;i<rows.length;i++)
{
var shopIdFetched = rows[i].shopId;
client.connection.query('select * from image where shopId=?',shopIdFetched,function(err,data){
if(data.length > 0){
console.log(rows[i],data);
}
});
}
}
});
}
当我给出行[0]和行1时,值将被提取。但我需要实现行[i]。
答案 0 :(得分:2)
你误解了异步调用是如何产生的。
运行这部分代码会发生什么?
for(var i=0;i<rows.length;i++)
{
var shopIdFetched = rows[i].shopId;
client.connection.query(...) //these are asynchronous methods
}
对于rows.length=10
,它将调用client.connection.query的10倍,这是不幸的异步方法,因此它尚未执行,但它将10个异步方法放到事件堆栈中。
此方法同步完成后,方法之一指示,对数据库的调用完成,方法执行,这是
if(data.length > 0){
console.log(rows[i],data);
}
但是此时,for-cycle已经完成i=10
,因此行[10]未定义(因为对于rows.length=10
,您有rows[0]
到{{1}的数据}}
一种解决方法是将另一种方法放到内部范围,类似这样
rows[9]
同样的事情可以写成这个
for(var i=0;i<10;i++)
{
x(i);
}
function x(i){
console.log(i);
//this i will be same even after asynchronous paradighm
}
在你的情况下
for (var i = 0; i < 10; i++) {
(function(i){
console.log(i);
})(i)
}
为了更好地理解,这将做同样的
for(var i=0;i<rows.length;i++)
{
(function(i){
var shopIdFetched = rows[i].shopId;
client.connection.query('select * from image where shopId=?',shopIdFetched,function(err,data){
if(data.length > 0){
console.log(rows[i],data);
}
});
})(i);
}
在前面的示例中,我们只使用不同的变量 for(var index=0;index<rows.length;index++)
{
(function(i){
var shopIdFetched = rows[i].shopId;
client.connection.query('select * from image where shopId=?',shopIdFetched,function(err,data){
if(data.length > 0){
console.log(rows[i],data);
}
});
})(index);
}
隐藏变量i
(如果创建了更多具有相同名称的变量,则将选择最内部范围内的变量)
答案 1 :(得分:1)
你不能在异步回调中依赖i
,因为它在被调用的时间处理程序中被更改了。
您应该创建一些范围来保存迭代数据(i或行)。
使用Array.prototype.forEach
:
rows.forEach(row => {
var shopIdFetched = row.shopId;
client.connection.query('select * from image where shopId=?',shopIdFetched,function(err,data){
if(data.length > 0){
console.log(row,data);
}
});
});
使用IIFE
:
for (var i=0; i<rows.length; i++) {
!function(i) {
// here you can use `i`/`rows[i]` without initial issue
}(i);
}