Nodejs - Expect for to run all pool.query by the end

Asked

Viewed 112 times

0

I have a small problem and as much as I have tried to find a solution, I cannot think of a great one. So I have come to ask for your help!

So here’s the thing, I’m currently developing a betting site (of CSGO game skins) and my problem is with Nodejs (Socket Server) due to the queries it makes in the database. In some functions it is necessary to loop with the 'for' by all the Ids of an Array, and each 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 doesn’t even consult everyone and already runs the final code, I tried to use a 'setTimeout' but it’s a very bad idea because there is never certainty if there will be some slowness in the data query with the database, or even if the array is too large and will need to perform many queries until it can display the final result. So often the end result always lacks 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);

1 answer

1


The Problem

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


NOTE: Below is a possible solution for your problem, and some improvements you can apply in your code, if the version of your Node is 6.x


Possible Solution

To achieve these values, in a way that does not impair the performance of your application 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
  })

Improvements in the code

You can improve your code by applying Arrowfunctions, trade in var for Let and const and learn a lot about Promises

Browser other questions tagged

You are not signed in. Login or sign up in order to post.