事件循环
单线程
-
.JavaScript是单线程
javascript是单线程,无论后面加了什么标准,什么操作,都不能改变javascript单线程的本质。原因就是,如果两个线程同时操控dom,那浏览器应该听谁的呢?为了避免这个问题,javascript只能是单线程。 -
但是浏览器是多线程的,除了js引擎线程,还有UI渲染线程,http请求线程等等。
-
.多线程共享运行资源,浏览器中js可以操作dom,会影响UI渲染,所以js引擎线程和UI渲染线程是互斥的,当js执行时会阻塞UI的渲染,如alert。
异步任务
-
js是单线程语言,浏览器只分配给js一个主线程,用来执行任务(函数),但一次只能执行一个任务,这些任务形成一个执行栈排队等候执行,但前端的某些任务是非常耗时的,比如网络请求,定时器和事件监听,如果让他们和别的任务一样,都老老实实的排队等待执行的话,执行效率会非常的低,甚至导致页面的假死。所以,浏览器为这些耗时任务开辟了另外的线程,主要包括http请求线程,浏览器定时触发器,浏览器事件触发线程,这些任务是异步的。
-
同步任务是指在主线程上排队执行的任务,只有前一个任务执行完毕,后一个同步任务才能执行。
-
异步任务是指不在主线程、而是在任务队列中的任务。只有当任务队列通知主线程,并且执行栈为空时,该任务队列中的任务才会进入主线程执行。
注意:那么问题来了,这些异步任务完成后,主线程怎么知道呢?
答案就是回调函数。
例如
setTimeout(function(){console.log(1);},50);
浏览器异步执行计时操作,当50ms到了后,会触发定时事件,这个时候,就会把回调函数放到任务队列里。整个程序就是通过这样的一个个事件驱动起来的。
所以说,js是一直是单线程的,浏览器才是实现异步的那个家伙。
事件循环
JS的运行机制如下:
(1)所有同步任务都在主线程上执行,形成一个执行栈。
(2)主线程之外,还存在一个”任务队列”。只要异步任务有了运行结果,就在”任务队列”之中放置一个事件。
(3)一旦”执行栈”中的所有同步任务执行完毕,系统就会读取”任务队列”,看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。
所以执行栈中的代码(同步任务),总是在读取”任务队列”(异步任务)之前执行。
EventLoop
主线程从”任务队列”中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。
6.jpg