Dan*_* T. 11 javascript ajax xmlhttprequest
假设我有一个执行标准AJAX请求的函数:
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');
Run Code Online (Sandbox Code Playgroud)
这段代码会导致浏览器启动一个AJAX请求,但是在函数的什么时候请求实际启动了?根据这篇文章:https://blog.raananweber.com/2015/06/17/no-there-are-no-race-conditions-in-javascript/
[Calling
xhr.onreadystate()aftersend()]是可能的,因为HTTP请求仅在当前作用域结束其任务后执行.这使程序员能够在他希望的任何位置设置回调.由于JavaScript是单线程的,因此只有在这个单个线程可以自由运行新任务时才能发送请求.HTTP请求被添加到要执行的任务列表中,该任务由引擎管理.
但是当我在发送调用之后立即在devtools中添加断点时:
我收到了网络请求,虽然处于待处理状态:
在断点处,XHR readystate是1,即XMLHttpRequest.OPENED.据MDN的文档,XMLHttpRequest.OPENED是指xhr.open()被称为:https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState
但是,如果我发表评论xhr.send(),只会.open()被称为:
然后我没有收到待处理的网络请求:
考虑到我可能需要函数范围结束以便实际发送请求,我将断点移到函数调用之后(并修改代码以查看XHR readyState):
但我仍然得到待处理的网络请求:
似乎调试器不仅冻结了代码执行,还冻结了任何网络请求.这是有道理的,因为您不希望在断点时完成网络请求,但这也使得无法确定网络请求何时实际启动.
我的问题是,请求实际发送到什么程度?调用xhr.send()只是设置请求,但要求函数范围在请求启动之前结束吗?xhr.send()在函数范围结束之前是否立即启动请求?或者还有其他事情发生在这里?
send立即发起请求。MDN 的文档至少暗示了这一点。send
您链接到的博客的作者是正确的,即本身不存在竞争条件,但这并不能阻止您发生无序的情况。一个例子是,如果您加载多个<script>标签及其上async=true的集合。在这种情况下,如果一个脚本依赖于另一个脚本,则最终可能会出现事件序列不可预测的情况(这与竞争条件非常相似),因为两个异步事件在不同时间完成。
确实,您可以onreadystatechange在调用后进行设置send,因为即使请求请求立即失败,该事件也不会在函数作用域完成之前被调度。这里的延迟不是指网络请求的调度,而是指网络请求完成的事件的调度。
值得注意的是,网络本身不是由JavaScript处理的,而是由浏览器实现处理的,它是本机代码,并且可以是多线程的(尽管我不知道是否是)。这意味着浏览器完全有能力在 JavaScript 运行时处理网络任务。
| 归档时间: |
|
| 查看次数: |
302 次 |
| 最近记录: |