由于JavaScript在单个线程中运行,在发出AJAX请求后,后台实际发生了什么?我想更深入地了解这一点,任何人都可以解释一下吗?
答案 0 :(得分:205)
在封面下,javascript有一个事件队列。每次javascript执行线程完成时,它都会检查队列中是否还有另一个要处理的事件。如果存在,则将其从队列中拉出并触发该事件(例如,鼠标单击)。
ajax调用下的本机代码网络将知道何时完成ajax响应并且事件将被添加到javascript事件队列中。本机代码如何知道ajax调用何时完成取决于实现。它可以用线程实现,也可以是事件驱动本身(它并不重要)。实现的重点是,当完成ajax响应时,一些本机代码将知道它已完成并将事件放入JS队列。
如果当时没有运行Javascript,将立即触发该事件,该事件将运行ajax响应处理程序。如果当时正在运行某些内容,则当前执行的javascript线程完成时将处理该事件。不需要通过javascript引擎进行任何轮询。当一段Javascript完成执行时,JS引擎只检查事件队列以查看是否还有其他需要运行的事件。如果是这样,它会从队列中弹出下一个事件并执行它(调用为该事件注册的一个或多个回调函数)。如果事件队列中没有任何内容,则JS解释器有空闲时间(垃圾收集或空闲),直到某个外部代理将其他东西放入事件队列并再次唤醒它。
因为所有外部事件都通过事件队列,并且当javascript实际运行其他内容时没有触发事件,所以它保持单线程。
以下是一些有关细节的文章:
答案 1 :(得分:16)
您可以在javascript中找到有关事件处理的here非常完整的文档 它是由一个致力于Opera浏览器中的javascript实现的人编写的。
更准确地说,看看标题:“事件流”,“事件排队”和“非用户事件”:您将了解到:
注意:原始链接是:link,但现在已经死了。
答案 2 :(得分:0)
关于答案中提到的ajax实现,我想详细说明。
(常规)JavaScript执行不是不是多线程的-如上述答案中所述-但是,
AJAX responses
的实际处理(以及请求处理)是不是 Javascript,它通常是 多线程的。 (请参见上文将讨论的XMLHttpRequest的chromium source implementation)
我将解释一下,让我们看下面的代码:
var xhr = new XMLHttpRequest();
var t = Date.now;
xhr.open( "GET", "https://swx.cdn.skype.com/shared/v/1.2.15/SkypeBootstrap.min.js?v="+t(), true );
xhr.onload = function( e ) {
console.log(t() + ': step 3');
alert(this.response.substr(0,20));
};
console.log(t() + ': step 1');
xhr.send();
console.log(t() + ': step 2');
after an AJAX request is made
(在第1步之后),
然后,当您的js代码继续执行时(第2步及以后),浏览器将开始以下工作:1.格式化tcp请求2.打开套接字3.发送标头4.握手5.发送正文6.等待响应7。阅读标头8.阅读正文等。所有此实现通常在与您的js代码执行并行的其他线程中运行。例如,提到的Chrome实现使用ThreadableLoader进行深入了解(您还可以通过查看页面加载的“网络”标签获得一些印象,还会看到一些同时请求)。
最后,我要说-至少-您的大多数I / O操作可以同时进行(例如,您可以使用 await 来利用它)。但是与这些操作的所有交互(发布,js回调执行)都是同步的。