一般认为JavaScript本质上是单线程的,但它可以异步运行。我想知道像这样的单线程模型如何处理非阻塞的AJAX请求?
假设在浏览器中触发了非阻塞的AJAX请求,但没有立即得到响应。如果事件循环继续检查响应,那么执行是否会被阻止?当没有响应时,事件循环是否继续检查其状态并将任务“重新添加”到macrotask队列的后面?
根据我的理解,Node.js会默默生成线程来处理访问磁盘,数据库,网络套接字等的I / O操作。浏览器中的JavaScript是否也会产生线程来处理AJAX?
可以询问类似的问题:
var img = new Image();
img.onerror=function(){alert('error: '+this.src);}
img.onload=function(){alert('image loaded: '+this.src);}
img.src='path/to/image.jpg';
上面的最后一行代码是否会导致产生额外的线程,因为该语句似乎是非阻塞的?
答案 0 :(得分:4)
一般认为JavaScript本质上是单线程的,但它可以异步运行。
也许,但感觉不正确。 JavaScript的任何内容都不是本质上的单线程。普通环境中的JavaScript(浏览器,NodeJS)默认在单个线程上运行,但浏览器通过Web worker公开多个线程。在该特定情况下,通过仅允许它们通过消息传递而不是使线程能够直接共享相同数据来最小化多线程复杂性。其他环境(例如,JVM上的JavaScript)提供了具有共享访问权限的多线程的所有混乱。
我想知道像这样的单线程模型如何处理非阻塞的AJAX请求?
在浏览器上,有一个主要的JavaScript UI线程(每个窗口/选项卡),但浏览器不是单线程的。异步ajax请求将传递给浏览器的网络处理。
主JavaScript线程,实际上是JavaScript执行模型,基于job queue(HTML5 speec称之为任务队列,但JavaScript规范谈到“工作” “ - 这只是一个名字)。线程从队列中获取作业,运行该作业完成,然后选择下一个作业。 (这有点复杂,但这是基本的想法。)如果没有待处理的作业,则线程闲置等待一个。
因此,当请求完成(成功,超时等)时,浏览器会将作业排队,以便在发起请求的JavaScript线程的作业队列上调用ajax回调。
值得注意的是,这也是它为响应其他事件所做的工作,例如用户点击某些内容。
假设在浏览器中触发了非阻塞的AJAX请求,但没有立即得到响应。如果事件循环继续检查响应,那么执行是否会被阻止?
关键是线程不会不断检查回复。该线程只是查看作业队列。浏览器的网络处理程序处理网络请求的完成。
答案 1 :(得分:1)
免责声明:以下文字只是猜测。我不知道我在说什么。
实际上,处理器也可以处理异步事件。这称为硬件中断。因此,只要在设备的输入模块上收到新消息,它就会触发这样的中断,处理器将跳转到某个内存位置,称为中断处理程序,然后启动一个新的线程到处理输入,然后跳回到被中断的位置。所以基本上,如果请求被重写,js事件循环,浏览器线程甚至cpu可能暂停一秒(非常罕见)。如果响应进来,互联网模块唤醒CPU并启动中断处理程序,该处理程序启动处理它的内核模块,然后启动浏览器解析请求并启动js事件循环,传递ajax请求到了qeue。所以实际上,如果浏览器只运行在一个线程中(它没有),它甚至是可能的。