Alan Coromano
Alan Coromano

Reputation: 26008

Wait until ajax request has been completed

Here is a javascript function:

  function getValue(key) {
    var value;
    switch(_options.myType){
      case "cookie":
        value = readFromCookie(key);
        break;
      case "localStorage":
        value = readFromLocalStorage(key);
        break;
      case "db":
        //return value from the server
        // how do I wait for the result?
        $.ajax({
            type: "GET",
            url: "123",
            data: { .... },
            success: function(data){
               value = data; 
            }
        });
        break;
    }
    return value;
  };

In case of sending ajax request, I need to wait untill the ajax request has been completed. How can I do it?

Not that I can't leave the function without having the value calculated. Which means that I can't place a function inside success: handler which will return the value later (or perhaps I don't understand something?). So it must be calculated within the function getValue().

UPDATE

P.S. So how do refactor my code to be able to use callback inside success: handler? Here is the second part of the code:

MyClass123.prototype.myMethod = function(value) {
      //..............
      var var1 = this.getValue("key1");
      if (var1 == "123") { ... }
      else { .... }
      //..............
    }
  };

Upvotes: 0

Views: 3007

Answers (3)

T.J. Crowder
T.J. Crowder

Reputation: 1073968

See follow-up below

You could make the ajax request synchronous, but that's generally a bad idea (and jQuery won't support it much longer).

Instead, make getValue accept a callback:

function getValue(key, callback) {
   switch(_options.myType){
     case "cookie":
       setTimeout(function() {
           callback(readFromCookie(key));
       }, 0);
       break;
     case "localStorage":
       setTimeout(function() {
           callback(readFromLocalStorage(key));
       }, 0);
       break;
     case "db":
       //return value from the server
       // how do I wait for the result?
       $.ajax({
           type: "GET",
           url: "123",
           data: { .... },
           success: function(data){
              callback(data);
           }
       });
       break;
   }
}

Note that I'm using setTimeout for the readFromCookie and readFromLocalStorage callbacks. Why? Because if getValue might return its value asynchronously, it should always do so. using a timeout of 0 asks the browser to do it as soon as possible once control yields back to the browser (although it's usually clamped to no less than 5-10ms).


Re your comment below:

Have you read what I write? I said that I can't do it for some reason.

I missed that bit, but with all due respect, you can. It may require some refactoring of code, but you can do it, and should. This is how modern web applications work. If your structure doesn't support it, you need to fix the structure. You can use async: false on the request as a temporary workaround until you can do it properly. (Hey, we've all been there and had to do things like that.) Note that it's scheduled for retirement before too long (just jQuery's support of it, you'll still be able to use XHR directly to do synchronous requests).


Re your updated question, here's how you update that code:

MyClass123.prototype.myMethod = function(value) {
  this.getState("key1", function(var1) {
    //                           ^--- Note the var becomes an arg
    if var1 == "123"{ ... }
    else { .... }
  });
};

Note how little it actually changes. The logic that used to follow the call to getState instead goes into the callback you pass into it.

Upvotes: 8

techfoobar
techfoobar

Reputation: 66663

You can make the AJAX request synchronous by specifying async: false - which is not recommended but possible. If it absolutely is the case that your getValue() function should not return before the AJAX request returns, then async is the way to go.

$.ajax({
    type: "GET",
    url: "123",
    async: false // NEW
    data: { .... },
    success: function(data){
        value = data; 
    }
});

Alternative using then and when:

function getValue(key, callback) {
   switch(_options.myType){

     ...

     case "db":
       return $.ajax({ // note the 'return'
           type: "GET",
           url: "123",
           ...
       });
   }
}

and where you call it, call it like:

$.when(getValue()).then(function() {
   // do the rest here ...
});

Upvotes: 2

Pekka
Pekka

Reputation: 449385

The right thing to do is to restructure your program flow so you can place your logic in the success handler.

You can make Ajax requests synchronous by using the async option, but that is silly. It'll slow down your app, because the browser window freezes until the request comes back successful (or times out). It's not often used in JavaScript development and for good reason.

Upvotes: 2

Related Questions