views:

23801

answers:

5

Hello. I have a javascript widget witch provides standard extension points. One of them is the beforecreate function. It should return false to prevent an item from being created.

I've added an AJAX call into this function using jQuery:

beforecreate: function(node,targetNode,type,to) { 
 jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),
 function(result) {
  if(result.isOk == false)
   alert(result.message);
 });        
}

But I want to prevent my widget from creating the item, so I should return false in the mother-function, not in the callback. Is there any way to perform a synchronized AJAX request using jQuery or any other API? Thanks.

+48  A: 

From the Jquery docs: you specify the async option to be false to get a synchronous Ajax request. Then your callback can set some data before your mother function proceeds.

Here's what your code would look like if changed as suggested:

beforecreate: function(node,targetNode,type,to) {
    jQuery.ajax({
         url:    'http://example.com/catalog/create/' 
                  + targetNode.id 
                  + '?name=' 
                  + encode(to.inp[0].value),
         success: function(result) {
                      if(result.isOk == false)
                          alert(result.message);
                  },
         async:   false
    });          
}
Adam Bellaire
Exactly, it is impossible to use get(), post(), load() for synchronous calls. Only ajax() have "async" parameter, which can be set to "false".
SLA80
+7  A: 

Be very careful about doing synchronous AJAX requests. If the client code has to wait for the server then the browser will completely lock up and the user won't be able to do anything until the reply comes back.

17 of 26
sometimes this is what is required. Also, how is that any different from clicking on a link? you also have to wait (presumably longer) till the response comes back...
Bartosz Radaczyński
it's different because the user's input events are not being handled while the syncronous XMLHttpRequest is outstanding. which is generally NOT the case when the browser has issued a GET
Scott Evernden
+6  A: 

Good Post I was trying to do this and I wasn't setting the async to false.
I'm using BlockUI which "grays" out the screen and displays a loading message while the server is doing the work.

Brad8118
Thanks for the tip! For those unfamiliar with all jQuery methods, I think it's important to point out that $.get() does not provide synchronous functionality. What is happening here is that $.ajax() is a more abstracted ajax request that needs to replace $.get() when more options are needed, such as this scenario.
rooskie
A: 

Adam - terrific tip; I had been wrestling with trying to dynamically add a chart element within a div that was being populated through a jQuery load() call: it was the first 'A' in AJAX that tripped me up (because the call to populate the chart div was happening before the load() statement had completely updated the content of the div in question).

Changing one load() call to an explicit ajax() with async: false, did two things: it made the output tabs navigable more quickly, AND it enabled me to replace a fat, slow, SWF with a jqPlot chart element.

The page in question is here (an example with ASXCode pre-defined), but the logic is going to be extended so that I can used other jQuery libraries on dynamically-added content.

Brad8118 - you probably already know you can just use

$("#divName").html(/path/to/loading.gif) // little animated "Loading" gif
             .load(/path/to/load.php, {POST stuff}, callback);

That said, I like the 'growl' deelie on the examples page.

GT
+1  A: 

Excellent solution! I noticed when I tried to implement it that if I returned a value in the success clause, it came back as undefined. I had to store it in a variable and return that variable. This is the method I came up with:

function getWhatever()
{
 var strUrl = ""; //whatever URL you need to call
 var strReturn = "";

 jQuery.ajax({
  url:strUrl, success:function(html){strReturn = html;}, async:false
 });

 return strReturn;
}
James in Indy