I encountered the UI thread blocking problem caused by synchronous Ajax, and recorded it here.
The reason is this, because there are multiple similar asynchronous request actions on the page, in line with the principle of improving code reusability, I encapsulated a function named getData, which receives different parameters, is only responsible for obtaining data, and then puts data return. The basic logic is stripped out like this:
var result;
$.ajax({
url: "p.php",
async: false,
success: function(data) {
result = data;
}
});
return result;
}
var data = getData1();
alert(data);
});
Next, I need to add another function. Since the ajax request takes a certain amount of time, I need to have a loading effect on the page before sending the request, that is, a gif picture of "loading" is displayed, which must be seen by everyone. So my handler function becomes like this:
$(".loadingicon").show();
var data = getData1();
$(".loadingicon").hide();
alert(data);
});
sleep(3);
echo ("aaaaaa");
?>
setTimeout solves blocking problem
Now that we understand where the problem is, let's find a way to target it. In order to prevent the synchronous ajax request from blocking the thread, I thought of setTimeout, put the requested code in sestTimeout, and let the browser restart a thread to operate, won't it solve the problem? So, my code becomes like this:
$(".btn2").click(function() {
setTimeout(function() {
$.ajax({
url: "p.php",
async: false,
success: function(data) {
$(".loadingicon").hide();
alert(data);
}
});
}, 0);
});
The second parameter of setTimeout is set to 0, and the browser will execute it after a set minimum time. Regardless of the 3721, run it first and see.
As a result, the loading picture is displayed, but! ! ! Why doesn't the picture move, I'm obviously a dynamic gif. At this time, I quickly thought that although the synchronous request is delayed, the UI thread will still be blocked during its execution. This blockage is pretty awesome, even the gif image doesn't move, it looks like a static image.
The conclusion is obvious that setTimeout can cure the symptoms but not the root cause, which is equivalent to "slightly" asynchronizing the synchronous request, and then it will still enter the nightmare of synchronization and block the thread. Scenario failed.
Time to use Deferred
After jQuery version 1.5, the Deferred object was introduced, which provided a very convenient generalized asynchronous mechanism. For details, please refer to this article by Mr. Ruanyifeng http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html .
So I rewrote the code with the Deferred object, as follows:
function getData3() {
$.ajax({
url: "p.php",
//async : false,
success: function(data) {
defer.resolve(data)
}
});
return defer.promise();
}
$(".btn3").click(function() {
$(".loadingicon").show();
$.when(getData3()).done(function(data) {
$(".loadingicon").hide();
alert(data);
});
});
You can see that I removed async:false in the ajax request, which means that the request is asynchronous again. Also, please pay attention to this sentence in the success function: defer.resolve(data), the resolve method of the Deferred object can pass in one parameter, any type. This parameter can be obtained in the done method, so the data we request asynchronously can be returned in this way.
So far, the problem has been solved. Deferred objects are so powerful and convenient that we can put them to good use.
Final note: This article is taken from other sites and is only used as a record (my own ability to organize is slightly weak :))