0

I have some javascript functions being called on Document Ready:

fogFields();
getLoS();
getShips();    

startGame();
getNextMove();

However, it is as though getNextMove() is being called first, most likely as all it does is an ajax call and alerts the result. All the other functions have more work, so, the first thing that happens on load is the getNextMove() alert, and in the background you can see that none of the other functions did their work. Until I click OK on the alert window, no results are shown. Can I make it so that until a function finishes, the next wont even start. Some functions call their own extra functions before they finish, and that works in order, but I cant do that with the whole code...

Dejan Biljecki
  • 595
  • 1
  • 5
  • 26

3 Answers3

3

Given the code in your question, there is no way the call to getNextMove can be invoked before startGame has been exited, regardless of their contents.

It may be true that a function that has been scheduled asynchronously (via timeout, AJAX callback etc.) within startGame completes at any time before or after the invocation of getNextMove, but this is a separate issue. To resolve that issue we need to know more about the contents of the functions.

Asad Saeeduddin
  • 46,193
  • 6
  • 90
  • 139
  • Yes other functions have AJAX calls, there are no timeouts. – Dejan Biljecki Aug 01 '13 at 21:02
  • 1
    @user1479059 The callbacks (these are function in and of themselves) to the AJAX calls are being invoked after the top level function that dispatched the AJAX call is over. The solution depends on a couple of things. Do the callbacks to the earlier functions need to be invoked in a certain order relative to each other, or just whenever, as long as it is before `getNextMove`? – Asad Saeeduddin Aug 01 '13 at 21:07
  • The order of the AJAX calls (they are actually JQ AJAX) does not matter - I just want them to be executed before the getNextMove() function. I have also tried putting the first 3 functions in a new one called draw() - and getNextMove in gNM(), and instead of alerting I display the result of getNextMove to a div. – Dejan Biljecki Aug 01 '13 at 21:12
  • The gNM() is called after draw(), but still, gNM() changes the div, and then draw() changes it. Same thing happening... – Dejan Biljecki Aug 01 '13 at 21:13
  • Also, startgame() is empty for now, so it does not matter. – Dejan Biljecki Aug 01 '13 at 21:15
  • @user1479059 Rearranging the first three into a single function won't change anything, since they will still be invoked whenever the AJAX call gets back from the server (which is up to the whims of the user's connection). Consider taking a look at [this](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call) overview of when AJAX callback functions actually get invoked. In the meantime, please post the content of the functions (shortened or using dummy code) so I can try to outline a solution. – Asad Saeeduddin Aug 01 '13 at 21:19
0

If the other functions have an AJAX call in them, then these AJAX calls most certainly take a callback argument, which is a function that gets executes, when the AJAX call has finshed. Now, if you want to execute your functions in a way, the one function starts when the AJAX call of the previous function finished, you can add an additional callback argument to your own functions, which will then be passed to the AJAX calls. This should illustrate what I mean:

function logFields(callback) {
    ajaxCall(callback);
}

function getLoS(callback) {
    ajaxCall(callback);
}

function getShips(callback) {
    ajaxCall(callback);
}

function startGame(callback) {
    ajaxCall(callback);
}

function getNextMove() {
}

fogFields(function(){
    getLoS(function(){
        getShips(function(){
            startGame(function(){
                getNextMove();
            });
        });
    });
});
basilikum
  • 10,378
  • 5
  • 45
  • 58
  • The problem with this is that it makes your AJAX calls sequential instead of concurrent, and really slows you down. It should be possible to dispatch all the AJAX requests at once, and invoke the next callback in the sequence as soon as it becomes available. – Asad Saeeduddin Aug 01 '13 at 21:17
  • That's true. But I'm not sure if I understand your suggestion. What would be "the next callback" if you dispatch all the AJAX requests at once? Also, I'm not sure what the AJAX calls contain. Maybe they contain data from the results of previous calls. But sure, it probably would be better to have only one AJAX call, that simply does everything. – basilikum Aug 01 '13 at 21:27
  • `var callbackSeq = ["logFields", "getLoS", "getShips", "startGame"]; var loadedCallbacks = {}; function runLoadedCallbacks(name, newestCallback) {...};` The callback to each AJAX request contains a function that closes over the returned data and an identifier string. It passes this function to `runLoadedCallbacks`. `runLoadedCallbacks` adds the function to the `loadedCallbacks` object under the key corresponding to `key`, then starting at the beginning of `callbackSeq` runs and removes as many functions as it can, breaking when it finds a name that isn't in `loadedCallbacks`. – Asad Saeeduddin Aug 01 '13 at 21:36
  • As far as I understand, what you are suggesting is kind of a queue, that assures, that the callbacks run in the right order. Which is nice but it doesn't solve the problem of dependencies. What if you need the result of one AJAX call, to start the next one? The question doesn't really give enough information about what is really happening. He asked "Can I make it so that until a function finishes, the next wont even start" and that is basically what I responded to, since I don't know what happens inside of his functions. – basilikum Aug 01 '13 at 21:48
  • That's true. I didn't consider whether the result from a callback would be needed at the time when you're dispatching the AJAX request. However, based on [this comment](http://stackoverflow.com/questions/18004156/javascript-order-of-executing-functions/18004710?noredirect=1#comment26328884_18004226): **"The order of the AJAX calls (they are actually JQ AJAX) does not matter"**, I think the OP is only concerned about the order in which the callbacks are executed (perhaps not even that, in which case we could use a simple count variable that we can monitor on loop before invoking `gNM()`). – Asad Saeeduddin Aug 01 '13 at 22:00
  • @Asad ah ok, didn't see that comment. In this case, it would indeed be a lot better to just use a queue or a counter variable to check if all the AJAX calls have finished. Thanks for clearing that up. – basilikum Aug 01 '13 at 22:56
0

If all of your functions use a ajax call then just use promises. Simply return it, for example:

function fogFields(){
    return $.ajax();
};

and then just use .then:

fogFields().then(getLos());

more information about deffered object on jquery doc page if you use it. Or implementation in pure javascript you can find here and more theory here.
or another option, which I will not recommend you is to set async param in $.ajax call to false. Again it's for case you use jQuery.

Vadim Ivanov
  • 633
  • 1
  • 7
  • 16