2

This might be the opposite of my previous question here but anyway, I need to know its answer as well.

I have an Ajax call in my algorithm that I need to wait for it to run some code. There are two solutions:

1) The typical solution:

ajaxCall(function(result){
  //the code to run after the call is returned
});

2) The one I'm wondering if it can be an alternative:

res=null;
ajaxCall(function(result){
  res=result;
});
while(res==null)/*wait! but this will lock the GUI I guess*/;
//do the rest of the code because now res is initialized

The question is how can I write the second solution in an efficient way that doesn't freeze the GUI?

Community
  • 1
  • 1
AlexStack
  • 16,766
  • 21
  • 72
  • 104
  • 2
    Just make the ajax call synchronous. ref: https://developer.mozilla.org/en/XMLHttpRequest look for the async parameter. – Yoshi Mar 08 '12 at 09:00
  • Synchronous requests still lock the GUI. – Andy E Mar 08 '12 at 09:04
  • 1
    @AndyE Of course, that's the whole point of async and sync. But it's still better than a possibly infinite loop. – Yoshi Mar 08 '12 at 09:05
  • @Yoshi: but he asked for a way to do it without locking the GUI. Recommending that he make the request synchronous conflicts with that requirement and the best advice is still to rework the code so that it can run completely asynchronously. – Andy E Mar 08 '12 at 09:08
  • @AndyE Yeah ok, that may be. I probably just choked on seeing the while loop. ;) – Yoshi Mar 08 '12 at 09:10
  • @Yoshi, your first comment is the best answer to this question. Would you please write an answer so that I can mark it? – AlexStack Mar 08 '12 at 09:28

5 Answers5

3

I suggest hooking all dependent code to execute as a callback from your ajax call 's return. That way, all other javascript can continue to execute and you will not make your browser unresponsive for the duration of the call.

Alternatively, which is not something I would never ever do, you can make your ajax call synchronous, using async: false like so:

$.ajax({ url: ..., async: false });
Ioannis Karadimas
  • 7,746
  • 3
  • 35
  • 45
  • this solution uses JQuery, which is acceptable. However, Yoshi's answer is marked as the final answer because it uses pure Javascript. – AlexStack Mar 08 '12 at 09:38
3

Just make the ajax call synchronous.

ref: http://developer.mozilla.org/en/XMLHttpRequest

look for the async parameter

Yoshi
  • 54,081
  • 14
  • 89
  • 103
1

A generic answer:

There are only two methods available in async. programming: events and callbacks. Period.

(Technically speaking, there is not really a difference between the two on the lowest level, an "event" is just a (library) function - the one doing the event "firing" - executing all functions registered as listeners so it's the same as a callback - technically, i.e. when you write event.fire() or whatever the event syntax of your preferred lib it's synchronous invocation of all registered event handler functions). When to use one or the other is a matter of preference, convention and style when designing an API.)

Mörre
  • 5,699
  • 6
  • 38
  • 63
  • 1
    No, there are no threads! Pls. read up on "event loop" (google) :-) – Mörre Mar 08 '12 at 09:44
  • interesting, so the whole Javascript code runs in one thread, that's why Javascript code is "thread-safe" by nature? – AlexStack Mar 08 '12 at 10:04
  • Yes. See "workers" for how it is planned to achieve parallelism in JS (some JS implementations already support it), apart from running several (independent, not communicating with one another) JS VM instances in parallel. – Mörre Mar 08 '12 at 10:24
1

Javascript programming, especially AJAX, is asynchronous by definition. So if you have an algorithm that needs to "wait" for something, you're better off reconsidering the algorithm. Ironically enough, Javascript syntax is not best suitable for async programming, but there are many libraries that help you keep callbacks under control and avoid spaghetti code.

Example of callbacks spaghetti:

function ajaxRequest(url1, function() {
    animateSomething(div, function() {
        ajaxRequest(url2, function() {
            ....
        })
    })
})

the same with async.js looks much cleaner:

async.series([
    function(_) { ajaxRequest(url1, _) },
    function(_) { animateSomething(div, _) },
    function(_) { ajaxRequest(url2, _) }
])
georg
  • 211,518
  • 52
  • 313
  • 390
0

there are many ways to do this one. one of the is passing a callback to the ajax (or at least a reference of it). your code #1 would be an example of that.

another is that you have a notifier object which you add the ajax success call to it. then you can have other functions (one or more) plug into it to listen for a "success" announcement.

Joseph
  • 117,725
  • 30
  • 181
  • 234