函数调用中的什么时候是浏览器实际发起的AJAX请求?

时间:2017-02-26 06:35:18

标签: javascript ajax xmlhttprequest

假设我有一个执行标准AJAX请求的函数:

foreach (var process in csProcess) { //code }

此代码将导致浏览器启动AJAX请求,但该函数在什么时候实际启动了请求?根据这篇文章:https://blog.raananweber.com/2015/06/17/no-there-are-no-race-conditions-in-javascript/

  

[可以在function doXHR() { var xhr = new XMLHttpRequest(); xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts'); xhr.send(); xhr.onreadystatechange = () => { console.log('ready state change'); }; } doXHR(); console.log('done'); 之后调用xhr.onreadystate(),因为 HTTP请求仅在当前作用域结束其任务后执行。这使程序员能够在他希望的任何位置设置回调。由于JavaScript是单线程的,因此只有在这个单个线程可以自由运行新任务时才能发送请求。 HTTP请求被添加到要执行的任务列表中,由引擎管理。

但是当我在发送呼叫之后在devtools中添加断点时:

enter image description here

我确实收到了一个网络请求,虽然处于待处理状态:

enter image description here

在断点处,XHR send()为1,即readystate。根据MDN的文档,XMLHttpRequest.OPENED表示已调用XMLHttpRequest.OPENEDhttps://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState

但是如果我发表评论xhr.open()以便只调用xhr.send()

enter image description here

然后我没有收到待处理的网络请求:

enter image description here

考虑到我可能需要函数范围结束以便实际发送请求,我将断点移到函数调用之后(并修改代码以查看XHR readyState):

enter image description here

但我仍然收到待处理的网络请求:

enter image description here

似乎调试器不仅会冻结代码执行,还会冻结任何网络请求。这是有道理的,因为您不希望在断点时完成网络请求,但这也使得无法确定网络请求何时实际启动。

我的问题是,请求实际发送到什么程度?调用.open()只是设置请求,但要求函数范围在请求启动之前结束吗? xhr.send()是否在函数范围结束之前立即启动请求?或者还有其他事情发生在这里吗?

1 个答案:

答案 0 :(得分:2)

send立即发起请求。这至少由MDN's documentation for send.

暗示

您链接到的博客的作者是正确的,本身没有竞争条件,但这并不能阻止您发生乱序。例如,如果您使用<script>设置加载多个async=true标记。在这种情况下,如果一个脚本依赖于另一个脚本,则最终可能会出现无法预测的事件序列(与竞争条件非常相似),因为两个异步事件在不同时间完成。

确实可以在调用onreadystatechange之后设置send,因为即使请求请求立即失败,也不会在函数范围完成之前调度该事件。这里的延迟不是在调度网络请求,而是在调度事件时说网络请求已经完成。

重要的是要注意,网络本身不是在 JavaScript 中处理,而是由浏览器实现处理,这是本机代码,并且可以是多线程的(虽然我不知道是否它是)。这意味着浏览器完全能够在您的javascript运行时处理网络任务。