在nodejs中执行sql查询时返回的未定义值

时间:2016-06-08 12:47:08

标签: node.js express

我从具有表的数据库中获取值: tables

我的代码:

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);
            }

        });

     }

   }

 });
}

但是在显示结果时,第一个查询显示未定义的值。 enter image description here

当我给出行[0]和行1时,值将被提取。但我需要实现行[i]。

2 个答案:

答案 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);
}