2017-08-27 15 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ています。私はbizValuesにkのすべての値を設定しようとしています。

+1

IIFEは魔法のように同期していませんが、まだ非同期で、ループが終了したときに「ある程度後で」完了します – adeneo

+0

@adeneoどうすればこの方法に近づけることができますか? – RRP

答えて

0

あなたのコードは非同期ですが、しばらくしてからデータが取り込まれます。問題を解決するにはPromisesを試してください。あなたは約束の配列を作って、それぞれを並列/直列に呼び出すことができます。 Promise.all()を使用することをおすすめします。しかし、約束が破綻した場合には対応する必要があります。あなたはこのコードを変更し、短いPromise.allでpromise.all docs

を使用しようとすることができ

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の欠点は、catchブロックは、あなたが今、あなたはさらに、あなたのデータを処理することができ、成功ハンドラ内の任意の単一のiterable

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

私はちょうどあなたの推薦された方法を試しましたが、前と同じようにやっています。私の目的は、基本的にk番目の値ごとに、すべてのcountry_idのクエリを実行することです。上記の解決策では、最終応答は最後の要素 – RRP

関連する問題