当前位置: 首页 > Web前端 > JavaScript

单线程JavaScript是如何实现异步的?

时间:2023-03-27 12:26:10 JavaScript

前言众所周知,JavaScript是单线程的,但是不可避免的JavaScript也需要执行一些异步任务,比如下面的例子functionfoo(){console.log("first");setTimeout((function(){console.log('second');}),5);}for(vari=0;i<1000000;i++){foo();}从上面的例子中复制代码,执行结果会先全部先输出,再全部输出第二,而不是交替执行。在这个过程中,很明显会出现并发的异步任务,那么问题来了,单线程JavaScript是如何实现异步的呢?为什么JavaScript是单线程的?作为一个Java程序员,在知道JavaScript是单线程之后,第一反应是疑惑。为什么语言被设计成单线程的?为什么不能使用多线程来提高效率呢?JavaScript的单线程与它的使用有关。作为一种浏览器脚本语言,JavaScript的主要目的是与用户交互和操作DOM。这就决定了它只能是单线程的,否则会带来非常复杂的同步问题。例如,假设JavaScript同时有两个线程,一个线程向某个DOM节点添加内容,另一个线程删除这个节点,那么浏览器应该以哪个线程为基础呢?因此,为了避免复杂性,JavaScript从一开始就是单线程的,这已经成为这门语言的核心特征,以后也不会改变。JavaScript是如何实现异步的?明白了为什么JavaScript是单线程的,那么它是如何实现异步的呢?JavaScript的异步能力主要是由JavaScript运行环境JavaScriptRuntime的运行环境提供的,它是JavaScript代码运行的地方。例如,JavaScript可以在chrome或node中执行。chrome和node都是JavaScriptRuntime。从上图可以看出,JavaScriptRuntime主要包括JsEngine和WebAPI。JsEngine将我们编写的JavaScript转换为更高效的机器代码以获得更好的性能。chrome浏览器中的JavaScript由V8引擎处理。V8引擎主要包括两部分,内存堆和执行栈。内存堆用于分配JavaScript程序使用的内存。执行栈:在执行栈中,你的JS代码是逐行读取执行的。除了引擎,JavaScriptRuntime还提供了WebAPI用于JS代码调用。WebAPI提供网络请求、定时器、事件监控等多种能力。因为JSRuntime不是单线程的,它持有一个线程池。因此,WebAPI代码运行在其他线程上,自然而然地提供了异步能力。事件循环机制JS分为同步任务和异步任务。同步任务在主线程上执行,形成一个执行栈。异步任务,在异步任务执行完成后,会往事件队列中加入各种事件,当栈中的代码执行完毕后,会读取事件队列中的事件,执行那些回调。需要注意的是事件循环机制,一旦执行栈中的所有同步任务执行完毕(此时JS引擎空闲),系统会读取任务队列,将可运行的异步任务添加到可执行文件中堆。所以setTimeout设置的时间是不准确的。可能压入事件列表的时候,主线程还没有空闲,正在执行其他代码,所以出错了。总结JavaScript本质上是一种运行在浏览器中的脚本语言。为了简化和避免在操作DOM时引入同步问题,JavaScript被设计为单线程语言。JavaScript的异步能力是由运行时环境提供的。通过WebAPI和事件循环机制,单线程JS也可以执行异步任务。最后,如果您觉得这篇文章对您有点帮助,请点个赞。或者可以加入我的开发交流群:1025263163互相学习,我们会有专业的技术解答。如果您觉得这篇文章对您有用,请给我们的开源项目一个小星星:http://github。crmeb.net/u/defu非常感谢!完整源码下载地址:https://market.cloud.tencent....PHP学习手册:https://doc.crmeb.com技术交流论坛:https://q.crmeb.com