views:

91

answers:

4

the question is fairly simple and technical:

var it_works = false;

$.post("some_file.php", '', function(data) {

     it_works = true;

});

alert(it_works); # false (yes, that 'alert' has to be here and not inside $.post itself)

What I want to achieve is:

alert(it_works); # true

Is there a way to do that? If not can $.post() return a value to be applied to it_works?

+3  A: 

It seems that your problem is simply a concurrency issue. The post function takes a callback argument to tell you when the post has been finished. You cannot make the alert in global scope like this and expect that the post has already been finished. You have to move it to the callback function.

Hosam Aly
+6  A: 

Try to use synchronous (blocking) request.

var it_works = false;

jQuery.ajax({
  type: "POST",
  url: 'some_file.php',
  success: function (data) {
    it_works = true;
  }, 
  async: false
});​

alert(it_works);

Requests are asynchronous (non-blocking) by default which means that the browser won't wait for them to be completed in order to continue its work. That's why your alert got wrong result.

Now, with jQuery.ajax you can set the request to be synchronous, which means that the script will not continue to run until the request is not finished.

Another way is to refactor your code so that the data would be passed to a callback function as soon as the request is finished. This is the preferred way.

Asynchronous programming is slightly more complicated because the consequence of making a request is encapsulated in a function instead of following the request statement. But the realtime behavior that the user experiences can be significantly better because they will not see a sluggish server or sluggish network cause the browser to act as though it had crashed. Synchronous programming is disrespectful and should not be employed in applications which are used by people.

Douglas Crockford (YUI Blog)

galambalazs
My bad, beat me to it.
mattbasta
@mattbasta no problem :)
galambalazs
But note that this will kill usability if `some_file.php` preforms a lot (expensive) operations.
Felix Kling
@Felix Yes, but there are cases when synchronous I/O is essential. It's a tool that shouldn't be overused. Best to be avoided, one might say.
galambalazs
and **please note** that the question was `alert has to be here not inside. Is there a way to do that?`
galambalazs
@galambalazs I think your answer should mention the pitfalls of creating a synch xhr call
redsquare
Updated the the answer with a quote from Crockford.
galambalazs
+1  A: 

AJAX stands for Asynchronous JavaScript and XML. Thus, the post to the server happens out-of-sync with the rest of the function. Try some code like this instead (it just breaks the shorthand $.post out into the longer $.ajax call and adds the async option).

var it_works = false;

$.ajax({
  type: 'POST',
  async: false,
  url: "some_file.php",
  data: "",
  success: function() {it_works = true;}
});

alert(it_works);

Hope this helps!

mattbasta
A: 

The reason your code fails is because post() will start an asynchronous request to the server. What that means for you is that post() returns immediately, not after the request completes, like you are expecting.

What you need, then, is for the request to be synchronous and block the current thread until the request completes. Thus,

var it_works = false;

$.ajax({
  url: 'some_file.php',
  async: false,  # makes request synchronous
  success: function() {
    it_works = true;
  }
});

alert(it_works);
Jesse Dhillon