Wait for Ajax return in synchronous function

Asked

Viewed 24,198 times

14

I have an operation that I need to perform synchronously, but part of the information I need can only be obtained via Ajax.

I tried to synchronise everything with a wait for Ajax to return. The problem is that as long as any function is running, Ajax events that handle return successfully do not run.

That’s an example of what I’m doing:

function foo () {
    var a = false;
    $.ajax({
        url: "foo" // substitua por qualquer URL real
    }).done(function () {
        a = true;
    });

    while(!a) { } // Isto é apenas para se ter uma espera.
    alert(a); // Isso nunca vai executar
}
foo();

And it has generated me race condition: the function associated with the event done shall not execute as long as the while is iterating, and the while will never end while the event done not executed.

Is there any way to achieve my goal?

  • It depends a little on what you want to do, but can always call a closed function out of .done() passing the ajax answer as parameter. You can add more code to better understand your problem?

  • Have you ever tried to raise an exception if there is no response from the server? while inside you test if the waiting time is greater than 5 * 60 * 1000 (5 minutes) if true then triggers an exception warning that there was no server response...

  • @Sergio the problem is simple... Just wait, within a synchronous function, for the return of an asynchronous call. I want to force an operation to be synchronous. I put a little more code just to illustrate better.

  • 1

    @Renan joined a jsFiddle to my comment above. Option is to use async: false as the bfavaretto suggested, taking into account the warnings and problems that this can bring.

  • @Renan What prevents you from calling a function with the desired behavior within the done?

  • @Luizfilipe Nada, just want to perform an entire sequence in a single method. But I’m evaluating the best way to do it yet. Anyway, the bfavaretto’s response was on the fly.

  • Have you tried a standby solution with setInterval? http://jsfiddle.net/YnbL4/

  • @Luizfilipe I will try something like this, or transfer the logic to done.

Show 3 more comments

3 answers

16


Yes, but first I need to make it clear that use ajax synchronously is highly contraindicated. The user interface will be frozen until the return of ajax.

The code for this in jQuery is:

var a;
$.ajax({
    url: "foo", // substitua por qualquer URL real
    async: false
}).done(function () {
    a = true;
});
console.log(a);

The while doesn’t work because it’s blocking the only thread used in JS. While the code does not exit the while, the Event loop does not progress, and asynchronous events (the done/complete ajax included) are never processed. And so the value of a never changes, and the while never ends, it’s an endless loop.

  • Now I feel bad I didn’t read the manual... async: false was the jump of the cat itself.

  • 3

    But it doesn’t hurt to insist, @Renan: if you can change the code to work asynchronously, do this.

  • 1

    You can be sure that I will :) I found better ways to solve my problem here, but still it is interesting to know the synchronous option for the method call ajax jQuery.

  • And I as a good Noob did an immense gambiarra in my project to run the rest of a function only after the ajax returned something. Bendito Stackoverflow.

  • @Joaopaulo You probably did the right thing, ajax is made to be used asynchronously.

3

Have you tried using callbacks?

function foo (callback) {
  $.ajax({
      url: "/minha_api",
      myCallback: callback,
      success: function(){
        this.myCallback(true);
      }          
  });     
}

foo(function(a){
   alert(a);
});

2

In the latter case, when nothing is working:

function foo () {
    var a = false;
    $.ajax({
        url: "foo" // substitua por qualquer URL real
    }).done(function () {
        a = true;
    });

    setInterval(function () {
        if (a) {
            alert(a); // Isso pode acontecer
        }
    }, 100);
}

foo();

Browser other questions tagged

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