想象一下,在由几个不同小部件组成的应用程序中。触发事件时,窗口小部件会清除其当前数据,执行AJAX请求,然后在响应返回时输入新信息。
以下是触发该事件时会发生什么的简化示例:
for (var i = 0; i < 10; i++) {
// Do an AJAX post
$.ajax(document.location.href, {
data: {
name: ‘Zach Gardner’
},
method: ‘POST’
});
// Do some expensive DOM stuff
for (var j = 0; j < 100; j++) {
var el = document.createElement(‘div’);
document.body.appendChild(el);
for (var k = 0; k < 100; k++) {
var child = document.createElement(‘div’);
el.appendChild(child);
el.removeChild(child);
}
}
}
Here is a JSFiddle of the code above
如果你打开Fiddler并在Chrome中运行它,你会发现AJAX请求很快就完成了。
Chrome http://zgardner.us/wp-content/uploads/2014/08/chrome.png
但是如果你在IE中做同样的事情(在10,11,12预览中测试过),你会发现请求需要更长的时间:
IE http://zgardner.us/wp-content/uploads/2014/08/ie.png
我们发现当jQuery执行对xhr的send方法的调用时,IE将创建请求。但它会保留请求,直到调用堆栈清空为止。
IE Fiddler http://zgardner.us/wp-content/uploads/2014/08/ie1.png
注意ClientBeginRequest和ClientDoneRequest之间的显着滞后。我们发现ClientDoneRequest总是在线程结束的几毫秒内。
这仅适用于POST AJAX请求。 GET的ClientBeginRequest和ClientDoneRequest总是在几毫秒之内。
另请注意,此问题也出现在IE的开发工具中:
IE Network http://zgardner.us/wp-content/uploads/2014/08/ie-dev-tools.png
如果你检查一个单独的请求,你可以在第二个开始,也就是它发送请求正文时,花了4.32秒:
IE First Request http://zgardner.us/wp-content/uploads/2014/08/ie-timings.png
为什么会这样?
有关更详细的说明,请参阅my blog post。
答案 0 :(得分:4)
由于Internet Explorer的源代码不是免费提供的,因此只有IE开发人员才能更详细地回答您的问题。
Web浏览器使用执行队列实现异步。有一个线程,它从UI和AJAX(和其他任务源)参加排队的任务。也就是说,它只能一次发生一次操作。
另一方面,UI优先于任何其他任务,因此,DOM操作应该在AJAX调用之前执行。当您发送AJAX请求时,可能需要很短的CPU时间来发送请求,但是如果您执行大量的UI工作,则可能需要更长的时间来结束整个AJAX请求,因为UI > AJAX
在优先级方面。 / p>
您在问题中描述的案例是Internet Explorer中的实现细节。 Chrome和Firefox在任务优先级方面可能会更好,但无论如何,我不会想到在发送大量AJAX请求时尝试一次追加100个DOM元素的情况。 您需要优化代码而不是期望Web浏览器优化学术/边缘案例。
例如,您可能不会逐个向文档元素添加100个DOM元素。您可以创建一个容器(即document.createElement("div")
),然后添加100个元素,而容器未附加到DOM,最后将整个容器添加到DOM。这将在单个绘制事件中添加这100个元素,这样会更便宜,并且由于任务优先级划分,其他类似AJAX的东西应该在更短的时间内执行。
另外,我不确定你是否知道Fiddler减速请求(它是一个调试器,有性能损失)。
您应该在SO:How does JavaScript handle AJAX responses in the background?
中查看此其他问答答案 1 :(得分:0)
当浏览器闲置时,两个浏览器都会进行Ajax调用。&#34; Chrome在操作DOM方面要比IE好得多,只有似乎才能立即调用Ajax。
但是,如果删除此行:
el.removeChild(child);
...你会注意到Chrome需要大约。进行第一次Ajax呼叫的时间要长四倍,然后是快速连续的九次呼叫。
当Chrome要求创建然后移除相同节点时,Chrome可能会进行一些优化。这可以被视为边缘情况,&#34;哪个Chrome比IE更好。
在任何情况下,在多线程JavaScript出现之前,代码优化是处理这种情况的最佳方式。