2017-08-27 144 views
0

我在for循環中執行sql查詢,執行查詢的函數是異步操作。所以我將這個異步操作封裝在一個即時調用函數中。在for循環中執行查詢

for(var k in bizValuesObj){ 
    if(existingCountries.hasOwnProperty(bizValuesObj[k]["country"])){ 
     country_id = existingCountries[bizValuesObj[k]["country"]]; 
    } 

    var productName = bizValuesObj[k]["product"]; 
    var bizTypes = bizValuesObj[k]["bizTypes"]; 
    var getproductIdQuery = "SELECT `id` FROM `product` WHERE name = ? AND country_id = ?"; 

    (function(){ 
     connection.query(getproductIdQuery, [productName, country_id], function(err, result){ 
      if(err){ 
       console.error("Error getting product id:", err.stack); 
      } 
      product_id = result[0].id; 
      for(var j= 0; j < bizTypes.length; j++){ 
       var temp = []; 
       temp.push(bizTypes[j]); 
       temp.push(country_id); 
       temp.push(product_id); 
       bizValues.push(temp); 
      } 
     }); 
    })(k); 
} 

此刻,我不清楚爲什麼bizValues沒有得到填充,直到主循環結束。我試圖爲每個k值填充bizValues

+1

IIFE不會神奇地使它同步,它仍然是異步的,並在「稍後一段時間」完成,最有可能當循環完成時 – adeneo

+0

@adeneo我該如何解決這個問題? – RRP

回答

0

你的代碼是異步的,它會在一段時間後被填充。您應該嘗試使用Promises來解決您的問題。你可以創建一個承諾數組,然後並行/串行地調用它們中的每一個。我會推薦使用Promise.all()。但是你必須處理承諾失敗的情況。請參考下面的代碼

function getPromise(getproductIdQuery){ 
    return new Promise(function(resolve, reject){ 
      connection.query(getproductIdQuery, [productName, country_id], function(err, result){ 
       if(err){ 
        console.error("Error getting product id:", err.stack); 
        reject(err); 
       } 
       product_id = result[0].id; 
       for(var j= 0; j < bizTypes.length; j++){ 
        var temp = []; 
        temp.push(bizTypes[j]); 
        temp.push(country_id); 
        temp.push(product_id); 
        bizValues.push(temp); 
       } 
       resolve(true); 
      } 
    }) 
} 

let promiseArray = []; 
for(var k in bizValuesObj){ 
    if(existingCountries.hasOwnProperty(bizValuesObj[k]["country"])){ 
     country_id = existingCountries[bizValuesObj[k]["country"]]; 
    } 

    var productName = bizValuesObj[k]["product"]; 
    var bizTypes = bizValuesObj[k]["bizTypes"]; 
    var getproductIdQuery = "SELECT `id` FROM `product` WHERE name = ? AND country_id = ?"; 
    promiseArray.push(getPromise(getproductIdQuery)); 
} 

Promise.all(promiseArray).then(function(){ 
    // here you would find temp array populated 
}) 
+0

我試過你的解決方案,我確實得到了repsonse,但country_id只是指臨時數組中的最後一個國家 – RRP

1

你可以嘗試改變這種代碼,並使用promise.all docs

總之Promise.all需要承諾的陣列和執行,只有當所有的異步數據有諾被取走。一個優點/ Promise.all的缺點是catch塊被調用時,你在任何一個迭代

for(var k in bizValuesObj){ 
    if(existingCountries.hasOwnProperty(bizValuesObj[k]["country"])){ 
     country_id = existingCountries[bizValuesObj[k]["country"]]; 
    } 

    var productName = bizValuesObj[k]["product"]; 
    var bizTypes = bizValuesObj[k]["bizTypes"]; 
    var getproductIdQuery = "SELECT `id` FROM `product` WHERE name = ? AND country_id = ?"; 
    // Async handling from here 
    const promiseArray = [] 
    promiseArray.push(connection.query(getproductIdQuery, [productName, country_id])); // <- This function is a promise 
} 

Promise.all(promiseArray).then((response) => { 
    // your response after all async fetches 
}).catch((error) => handle error) 

現在,在成功處理程序您可以進一步處理您的數據擊中了錯誤的時刻。

+0

我剛試過你推薦的方法,但它仍然和以前一樣。我的目標是對每個country_id執行查詢,所以基本上對於每個第k個值。通過上述解決方案,最終的迴應只有最後一個元素 – RRP