NodeJS - Wait for 'for' to execute all 'pool.query' until the end

0

I have a small problem, and no matter how hard I tried to find a solution, I can not think of an excellent one. So I come to ask for your help!

So here's the thing: I'm currently developing a betting site (from CSGO game skins) and my problem is on NodeJS (Socket Server) because of queries it makes in the database. In some functions it is necessary to loop the for for all the IDs of an Array, and each one of them will perform a Query (Query in the Database) and add a value of each one in a global variable. But most of the time he does not even consult all and already executes the final code, I tried to use a 'setTimeout' but the idea is very bad because there is never certainty if there will be some slowness in querying the data with the database, or even even if the array is too large and you will have to perform many queries before you can display the final result. So often the final result is always missing some values. Here is an example of the code (a part):

for(var i = 0; i < result.length; i++) {
            var ThisRes = result[i];

            var VS1_Value = 0.00;
            var VS2_Value = 0.00;

            var VS1_ItemsA = ThisRes.vs1_items.split(',');
            for(var i = 0; i < VS1_ItemsA.length; i++) { // REPETE AQUI BASTANTES VEZES CONFORME O TAMANHO DO ARRAY
                pool.query("SELECT * FROM gf_user_items WHERE assetid='"+VS1_ItemsA[i]+"'", function(err2,res2) {
                    if(err2) {
                        console.log(TagGF_Error+"Error Getting Item Details from DB! (AssetID:"+VS1_ItemsA[i]+")");
                        return;
                    }
                    if(res2.length > 0) {
                        var ThisVal = res2[0].price*1;
                        VS1_Value = VS1_Value*1 + ThisVal*1; // AQUI FAZ A SOMA
                    } else {
                        console.log(TagGF_Error+"Error Getting Item Details from DB! (Empty)(AssetID:"+VS1_ItemsA[i]+"|RES2_SIZE:"+res2.length+")");
                    }
                });
            }
            if(ThisRes.vs2_eid !== null && ThisRes.vs2_items !== null) {
                var VS2_ItemsA = ThisRes.vs2_items.split(',');
                for(var i = 0; i < VS2_ItemsA.length; i++) {
                    pool.query("SELECT * FROM gf_user_items WHERE assetid='"+VS2_ItemsA[i]+"'", function(err3,res3) {
                        if(err3) {
                            console.log(TagGF_Error+"Error Getting Item Details from DB! (AssetID:"+VS2_ItemsA[i]+")");
                            return;
                        }
                        if(res3.length > 0) {
                            var ThisVal = res3[0].price*1;
                            VS2_Value = VS2_Value*1 + ThisVal*1;
                        } else {
                            console.log(TagGF_Error+"Error Getting Item Details from DB! (Empty)(AssetID:"+VS2_ItemsA[i]+"|RES2_SIZE:"+res3.length+")");
                        }
                    });
                }
            }

            setTimeout(function() { // E APÓS TER EFETUADO TODAS AS SOMAS, SEGUE O RESTO...
                var TotalValue = VS1_Value*1 + VS2_Value*2;
                var GF_ThisGameData = {};
                GF_ThisGameData["game_id"] = ThisRes.id;
                GF_ThisGameData["f_side"] = ThisRes.f_team;
                GF_ThisGameData["vs1_eid"] = ThisRes.vs1_eid;
                GF_ThisGameData["vs1_items"] = ThisRes.vs1_items;
                GF_ThisGameData["vs1_value"] = VS1_Value.toFixed(2);
                GF_ThisGameData["vs2_eid"] = ThisRes.vs2_eid;
                GF_ThisGameData["vs2_items"] = ThisRes.vs2_items;
                GF_ThisGameData["vs2_value"] = VS2_Value.toFixed(2);
                GF_ThisGameData["total_value"] = TotalValue.toFixed(2);
                GF_ThisGameData["create_time"] = ThisRes.create_time;
                GF_ThisGameData["update_time"] = ThisRes.update_time;
                GF_ThisGameData["winner"] = ThisRes.winner;
                GF_NW_CoinFlipGames.push(GF_ThisGameData);
            }, 1500);
        }
        setTimeout(function() {
            console.log(TagGF+"CoinFlip Games: "+JSON.stringify(GF_NW_CoinFlipGames));
        }, 3000);
    
asked by anonymous 30.10.2017 / 18:25

1 answer

1

The Problem

First, let's talk about the problem with your code. The pool.query () function seems to be asynchronous / non-blocking , so iterating over it to get these values will not be possible, since it will not fire the callback you passed to it the instant you run pool.query (string, callback).

NOTE: Below is a possible solution to your problem, and some improvements you can apply in your code if your node version is 6.x

Possible Solution

In order to achieve these values, so that your application's performance does not hurt, we can use Promise

So we can do this:

var arrayPromise = [];

for(var i = 0; i < VS1_ItemsA.length; i++) { 
  var asyncFunc = new Promise(function(resolve, reject) {
    pool.query("SELECT * FROM gf_user_items WHERE assetid='"+VS1_ItemsA[i]+"'", function(err2,res2) {
      if(err2) {
        // logs de erro aqui...
        reject("mensagem de erro que você quiser");
      }
      if(res2.length > 0) {
        // faz a soma aqui ...
        resolve();
      } else {
        // logs de erro aqui...
        reject("mensagem que você quiser");
      }
    });
  });

  // Insere a promise no array
  arrayAsync.push(asyncFunc);
}

// Faz o mesmo para a segunda parte do código...

// Executa todas as promises
Promise.all(arrayPromise)
  .then(function(arrResults) {
    // Aqui você já vai ter sua variavel com o valor que você desejava, 
    // então pode colocar o que estava no "setTimeout" aqui
  })

Code Improvements

You can improve your code by applying ArrowFunctions , var and const and learn a lot about < in> Promises

    
30.10.2017 / 22:06