When Ajax sync requests, Google Chrome crashes. Switch to deferred

Source: Internet
Author: User

As the saying goes, death will not die, today to die a time, wrote a comparison of the two forces of the function, encountered the synchronization of Ajax caused by the UI thread blocking problem, in this record.

The reason for this is that because there are several similar asynchronous request actions on the page, and in the principle of improving code reusability, I encapsulate a function called GetData, which receives different parameters, takes care of the data, and then return the data. The basic logic is stripped out like this:

copy code
function getData1 () {        var result;
        $.ajax ({
             URL: ' p.php ',
            async:false,
            success:function (data) {
                 result = data;
           }
       });     return result;
}

Ajax here cannot be asynchronous, otherwise, when the function returns, the result is not assigned, and an error occurs. So I added a async:false. Looks like there's no problem. I call this function to get the data normally.

The code is as follows Copy Code
$ ('. Btn1 '). Click (function () {var data = getData1 ();
alert (data);
});

Next, to add another feature, because the AJAX request is time-consuming, so I need to make the request before the page has a loading effect, that is to display a "loading" of the GIF picture, presumably everyone has seen. So my handler function becomes this:

The code is as follows Copy Code
$ ('. Btn1 '). Click (function () {
$ ('. Loadingicon '). Show (); var data = GetData1 ();
$ ('. Loadingicon '). Hide ();
alert (data);
});

The request displays the loading picture before the request is completed and hides it. There seems to be no problem. To see the effect, my p.php code sleep for 3 seconds, as follows:

<?phpsleep (3); Echo (' aaaaaa ');? >
But when I ran the problem arose, I clicked the button did not appear as expected the loading picture, the page does not react. Ruled out long to find the reason, right here in Async:false.

The browser's rendering (UI) thread and the JS thread are mutually exclusive, and when the JS time-consuming operation is performed, the page rendering is blocked out. There is no problem when we execute asynchronous Ajax, but when set to synchronous requests, other actions (the code behind the AJAX function and the render thread) will stop. Even if my DOM action statement is the previous sentence of the initiating request, the synchronization request will "quickly" block the UI thread and not give it time to execute. This is why the code fails.

SetTimeout Solving blocking problems
Now that we understand where the problem is, we will find a way to do it. In order not to allow synchronous Ajax requests to block threads, I thought of settimeout, put the requested code into Sesttimeout, let the browser restart a thread to operate, do not solve the problem? Thus, my code becomes this:

The code is as follows Copy Code
$ ('. Btn2 '). Click (function () {
$ ('. Loadingicon '). Show ();
SetTimeout (function () {
$.ajax ({
URL: ' p.php ',
Async:false,
Success:function (data) {
$ ('. Loadingicon '). Hide ();
alert (data);
}
});
}, 0);
});

The second parameter of the settimeout is set to 0, and the browser executes after a set minimum time. No matter 3,721 run up first look.

The result loading picture shows out, but!!! How does the picture not move, I am clearly a animated GIF graph. This time I quickly thought, although the synchronization request deferred execution, but it will be during the execution of the UI thread to block. The block is pretty cool, and even the GIF doesn't move, it looks like a static picture.

Conclusion It is obvious that the settimeout symptom is not the root cause, equivalent to the synchronous request "slightly" asynchronous a bit, followed by a synchronous nightmare, blocking threads. Scenario failed.

It's time to use deferred.
After the 1.5 release, jquery introduced the deferred object, which provides a convenient generalized asynchronous mechanism. For more details, please refer to this article by Nanyi and I have rewritten the code with deferred object as follows:

The code is as follows Copy Code


function getData3 () {var defer = $. Deferred ();
$.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 the async:false from the AJAX request, which means that the request is asynchronous. Also note that this sentence in the Success function: Defer.resolve (data), the Resolve method of the deferred object can pass in an argument, any type. This parameter can be obtained in the Done method, so the data we request asynchronously can be returned in this way.

At this point, the problem has been solved. The deferred object is so powerful and convenient that we can make good use of it.

My entire test code is as follows, the prospective classmate can take to measure:

The code is as follows Copy Code


<button class= "btn1" >async:false</button><button class= "BTN2" >setTimeout</button>< Button class= "Btn3" >deferred</button>
<script>
function getData1 () {var result;
$.ajax ({
URL: ' p.php ',
Async:false,
Success:function (data) {
result = data;
}
}); return result;
}
$ ('. Btn1 '). Click (function () {
$ ('. Loadingicon '). Show (); var data = GetData1 ();
$ ('. Loadingicon '). Hide ();
alert (data);
});

$ ('. Btn2 '). Click (function () {
$ ('. Loadingicon '). Show ();
SetTimeout (function () {
$.ajax ({
URL: ' p.php ',
Async:false,
Success:function (data) {
$ ('. Loadingicon '). Hide ();
alert (data);
}
});
}, 0);
}); function getData3 () {var defer = $. Deferred ();
$.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);
});
});</script>

Ps:firefox have done optimization?

The above questions are consistent with the test results in Chrome and IE9. But when I was testing in Firefox, syncing Ajax didn't block the UI thread, which means the problem didn't exist at all. I did the test with other code, and in Firefox, the JS thread does block the UI thread, which is no doubt. One possible guess is that Firefox has been optimized for synchronous Ajax, and I'm not aware of what the truth is. Have the expert know also please pointing.

From: http://www.cnblogs.com/haogj/p/4480772.html

When Ajax sync requests, Google Chrome crashes. Switch to deferred

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.