Asynchronous Ajax callback
I am making the following ajax call:
def myfunction(var1, var2){
b1. $.ajax({
url: 'some_url2',
type: "POST",
data: {'mydata': var1, 'mydata2': var2},
success: function (data) {
b2. document.getElementById("successMessageAlert").style.display = "none";
},
error: function(xhr, errmsg, err) {
alert('error1 occurred');
b3. }
}
def function1() {
$.ajax({
url: 'some_url',
type: "POST",
data: formData,
success: function (data) {
var aData = JSON.parse(data);
b4. myfunction(getCookie('selected_Id'), aData);
b5. document.getElementById("successMessageAlert").style.display = "block";
b6. document.getElementById("successMessageText").innerHTML = "<strong>Success!</strong> The encoding record was saved successfully.";
}
},
error: function (xhr, errmsg, err) {
alert('error occurred')
}
});
}
I am also using the following code snippet for csrf:
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
The problem is that the instructions after myfunction
are executed before myfunction
. So, "successMessageAlert" appears briefly before hiding again.
I've used some breakpoints (b1-b6). Below is the order of their execution:
- b4
- b1
- b3
- b5
- b6
- b2
- b3
Based on reading a few related SO posts, I know this problem must have something to do with the asynchronous nature of the ajax calls, function beforesend
and callbacks, but I can't seem to put 2 and 2 together. Please help.
PS: I need to change the title of the post. But I cannot describe this problem succinctly.
source to share
Actually, the flow of execution is absolutely correct. I don't consider it to be anything related. beforeSend
Now you need to understand the nature of JavaScript ajax call. Ajax Call asynchronous
in nature.
asynchronous
means that whenever an ajax call is made, JavaScript does not wait for the call to complete and move on to the next line of code.
For example, in your case
After the b1
code moved to -> b3
Since JavaScript did not wait for the call to complete
Now the question is when will be executed b2
.
It depends on the network traffic, once the ajax call is complete the code will execute b2
.
How to handle this case:
There are two ways:
a) I will not suggest this. Use async:false
as a parameter in ajax call. When this parameter is specified in the ajax call, it says JavaScript, expecting
b2
and don't go to b3
.
Why am I not suggesting this
The call is synchronous, if your request takes 3 seconds then your site doesn't respond for 3 seconds.
b) Callback using the second approach:
This is a bit tricky but the best approach.
First, you need to define the code that depends on the completion of the ajax call, you can put all this code inside the function and execute it after the ajax call completes
Below is an example:
def myfunction(var1, var2 , callback){
$.ajax({
url: 'some_url2',
type: "POST",
data: {'mydata': var1, 'mydata2': var2},
success: function (data) {
document.getElementById("successMessageAlert").style.display = "none";
callback(); //execute the passed function now
},
error: function(xhr, errmsg, err) {
alert('error1 occurred');
}
}
def function1() {
$.ajax({
url: 'some_url',
type: "POST",
data: formData,
success: function (data) {
var aData = JSON.parse(data);
myfunction(getCookie('selected_Id'), aData ,function(){
//Code will get executed after ajax call completes
document.getElementById("successMessageAlert").style.display = "block";
document.getElementById("successMessageText").innerHTML = "<strong>Success!</strong> The encoding record was saved successfully.";
});
}
},
error: function (xhr, errmsg, err) {
alert('error occurred')
}
});
}
source to share
try using ajax call like this async:false
in youmyfunction
$.ajax({
url: 'some_url2',
type: "POST",
async:false,
data: {'mydata': var1, 'mydata2': var2},
success: function (data) {
document.getElementById("successMessageAlert").style.display = "none";
},
error: function(xhr, errmsg, err) {
alert('error1 occurred');
}
Please check the answer if it helps
source to share
In jQuery, ajax calls return a jqXHR object for asynchronous processing. Among other possibilities, it has a function .done
that binds a callback to get the ajax result after the request is done. It is very useful to return and use this object as it opens the door for various kinds of continuous processing.
As noted in other answers, it is not a great idea to make the ajax calls behave synchronously as this blocks all other processing and can lead to very bad UX.
You must use this in your code to manipulate only the UI:
function myfunction(var1, var2){
// I guess the "successMessageAlert" should be here, no?
document.getElementById("successMessageAlert").style.display = "none";
return $.ajax({
url: 'some_url2',
type: "POST",
data: {'mydata': var1, 'mydata2': var2},
/* success: function (data) {
document.getElementById("successMessageAlert").style.display = "none";
},*/ // <- Bring this back if that really what you wanted...
error: function(xhr, errmsg, err) {
alert('error1 occurred');
}
}
function function1() {
$.ajax({
url: 'some_url',
type: "POST",
data: formData,
success: function (data) {
var aData = JSON.parse(data);
myfunction(getCookie('selected_Id'), aData).done(function () {
document.getElementById("successMessageAlert").style.display = "block";
document.getElementById("successMessageText").innerHTML = "<strong>Success!</strong> The encoding record was saved successfully.";
});
},
error: function (xhr, errmsg, err) {
alert('error occurred')
}
});
}
source to share