2

I'm new to javascript, but I can't get my head around this problem. I have a function that upvotes a game:

function upVoteGame(name) {
  $.get("/get_gameValues", function(data) {
    var alreadyExist = false;
    var noVotes = false;
    var games;
    games = data;
    for (var i = 0; i < games.length; i++) {
      if (name === games[i].gameName) {
        alreadyExist = true;


        voteOperations();

        if (userLoggedIn == false) {
          alert("second");
          swal("Cannot post votes", "Please log in or register to vote", "error");
        }

        if (noVotesLeft == false && userLoggedIn == true) {
          $.ajax({
            url: '/editVotes/' + games[i]._id,
            type: 'PUT',
            data: {
              likes: games[i].likes + 1,
              totalVotes: data[i].totalVotes + 1
            },
            success: function(result) {
              alert(games[i].likes + 1);
            }
          });
        }
        refreshGameValues();
        break;
      }
    }

    //This is for us Developers!
    if (!alreadyExist) {
      $.post("/add_game_to_dB", {
        gameName: name
      }, function(result) {
        alert("Introduced " + name);
      });
    }
  });
}

Now I have the function that updates the user's votes left, voteOperations():

function voteOperations() {
  $.get("/users/get_current_user", function(data) {
    //var votes = 5;
    for (var i = 0; i < data.length; i++) {
      votesRemaining = data[i].votesRemaining;
      userLoggedIn = true;
      alert("votes left : " + votesRemaining);

      if ((votesRemaining - 1) < 0) {
        swal("No votes remaining", "Please wait 24 hours to get more votes", "error");
        noVotesLeft = true;
      }
      if (noVotesLeft == false) {
        $.ajax({
          url: '/users/updateUserDetails/' + data[i].user_name,
          type: 'PUT',
          data: {
            votesRemaining: votesRemaining - 1
          },
          success: function(result) {}
        });
      }
    }
  });
}

My problem is a simple problem. In the upVoteGame(name) function, I want the voteOperations() to execute before the if loop below it. However, when I run the code, the if loop below executes first and alerts the user that they are not logged in. When a user logs in, userLoggedIn is set to true, but the if loop executes firsts and tells them that they are not logged in, and then executes the voteOperations() function. I don't know why this is happening. How can I fix this so that voteOperations executes before the if loop?

phuzi
  • 12,078
  • 3
  • 26
  • 50
irish Senthil
  • 81
  • 1
  • 6
  • Your ajax operation contained in `voteOperations` is Asynchronous - for a description of what this means, look at this question [here](https://stackoverflow.com/questions/3393751/what-does-asynchronous-means-in-ajax). Essentially, this means that `$.get` will continue to run _along side_ the if statement. Whichever one completes first will be output first. Look at the comment below for a solution. – Lewis Apr 17 '18 at 09:58
  • This is because the voteoperations function has a get request which is asynchronous. You will need a callback function where you should include if condition – Harikrishnan N Apr 17 '18 at 09:58

3 Answers3

3

This is because the voteoperations function has a get request which is asynchronous. You will need a callback function where you should include if condition

You can try:

function upVoteGame(name) {
  vote(afterGet);
}

afterGet() {
    if condition here
}

function vote(callback) {
    $.get .... {
       //after getting data
       callback();
    }
}
Harikrishnan N
  • 874
  • 1
  • 10
  • 19
1

You problem occurs due to the asynchronous call of your $.get in the voteOperations function.

Since it is an asynchronous call your code continuous while your $.get is waiting to retrieve data and thus your if statement seems to trigger before your voteOperations function.

In simple words your function actually is triggered before the if statement but before it completes it's result the code continues and triggers your if statement.

You could put your if statement (logic) in the success callback of your vote operation function or use $.ajax with async:false which is not considered a good practice generally but I use it sometimes.

Something like that for example (for the second case)

     $.ajax({
        async: false,
        .....
        success: function (response) {
            //
        }
    });
Anastasios Selmani
  • 3,579
  • 3
  • 32
  • 48
  • I see... thanks for the info. I used a setTimeoutFunction for 100ms, which makes sure that the data is retrived, then executes the rest of the code. – irish Senthil Apr 17 '18 at 10:51
  • 1
    @irishSenthil I am afraid this is a very bad idea. You will just end up with a code that depends on the time the response is needed. Every time your backend is a little bit late on his response your code won't work. – Anastasios Selmani Apr 17 '18 at 12:01
0

Asynchronous calls can be handled with jquery function Deffered

function upVoteGame(name) {
    vote().then(doUpVoteGame(), handleError());
}

function doUpVoteGame() {
    ...
}

function handleError(e) {
    console.error("fail", e);
}

function vote() {
    var d = new $.Deferred();     

    $.get .... {
       d.resolve();
    }).fail(function(e) {
       d.reject(e);
    });

    return d;
}
bpu
  • 61
  • 5