Reputation: 2922
The jQuery docs strongly urge you not to set async
to false
when performing an $.ajax
request.
However, I'm seeing common solutions to synchronicity problems involve doing just this. And then I've seen people been chastised for going against the docs' recommendation.
With that said, I have attempted to use a promise to avoid using async:false
with no luck.
Here is the code I'm using. I have an onclick event that calls addToOrder
:
function saveTemplate() {
var formData = getFormData();
return $.ajax({
type: "POST",
url: "/p/session/save/" + sessionid + "/template/<?php echo $templateID ?>/",
data: formData,
async: true,
success: function(msg){
var rsp = $.parseJSON(msg);
if (rsp.response === 'Saved') {
sessionid = rsp.sessionid;
$("#save-preview-data-response").html(" " + rsp.response).fadeIn(100).delay(1000).fadeOut(1000);
} else {
$("#save-preview-data-response").css('color','#ff0000').html(" " + rsp.response).fadeIn(100).delay(1000).fadeOut(1000);
}
}
});
}
function addToOrder() {
var saved = saveTemplate();
var issaved;
saved.success(function(e) {
var rsp = $.parseJSON(e);
issaved = (rsp.response == 'Saved') ? true : false;
});
if(issaved) {
$.ajax({
type: "POST",
url: "<?php echo $baseURL; ?>addToOrder/respond/json",
data: "sid=" + sessionid,
async: true,
success: function(msg){
var rsp = $.parseJSON(msg);
if (rsp.response === 'Saved') {
alert(msg);
}
}
});
}
}
issaved
will always evaluate to false, as it is being evaluated before saveTemplate
has had time to run. The only solution I have found is to set async:false
but I am taking the warnings I've seen serious and would rather not. What other solutions are there?
Upvotes: 5
Views: 4070
Reputation: 27609
You could change the SaveTemplate function to accept a parameter that is a function that is run on save. Then in your addToOrder function you can either generate an anonymous function with the code you have in there or refactor so that most of that code is in another function that you can pass by name.
The idea is that with async code the moment you make an async call you stop working on that issue there (ie the save code) and pick up running in your callback. You could keep doing unrelated stuff after the async call (eg putting up a message to the user sayign "please wait") but any further code related to the save must be in a function triggered by the callback set in the success property of the ajax configuration.
Upvotes: 1
Reputation: 1074485
Tactics to avoid using async:false with jQuery?
Learn to love callbacks. :-) When people do this:
// The synchronous way
function doSomething() {
var foo;
$.ajax({
url: "/the/url",
async: false,
success: function(response) {
foo = response.foo;
}
});
return foo;
}
// ...somewhere else, we use it
function flurgle() {
var bar = /* go get `bar` from somewhere */;
var x = 52;
if (doSomething() === bar) {
x -= 10;
}
niftyFunctionUsing(x);
}
...the event-driven, asynchronous way really isn't that much different:
// The asynchronous way
function doSomething(callback) {
$.ajax({
url: "/the/url",
success: function(response) {
callback(response.foo);
}
});
}
// ...somewhere else, we use it
function flurgle() {
var bar = /* go get `bar` from somewhere */;
var x = 52;
doSomething(function(foo) {
if (foo === bar) {
x -= 10;
}
niftyFunctionUsing(x);
});
}
Since callbacks frequently involve closures (the above ones do, that's how we're accessing x
and bar
), this article from my blog may be helpful: Closures are not complicated
Upvotes: 12
Reputation: 4297
Put the second .ajax() call inside of the .success() function of the first.
Upvotes: 0