js事件循环机制(event loop)
JavaScript引擎是单线程
JavaScript 引擎是单线程,也就是说每次只能执行一项任务,其他任务都得按照顺序排队等待被执行,只有当前的任务执行完成之后才会往下执行下一个任务。
JavaScript事件循环机制
Javascript 有一个 main thread 主线程和 call-stack 调用栈(执行栈),所有的任务都会被放到调用栈等待主线程执行。
-
JS调用栈
JS 调用栈是一种后进先出的数据结构。当函数被调用时,会被添加到栈中的顶部,执行完成之后就从栈顶部移出该函数,直到栈内被清空。
-
同步任务、异步任务
JS单线程中的任务分为同步任务和异步任务。同步任务会在调用栈中按顺序排队等待主线程执行,异步任务则会在异步任务有了结果将注册的回调函数添加到任务队列中等待主线程空闲(执行栈内被清空)时,加入到执行栈等待主线程执行。任务队列是先进先出的数据结构。
-
event loop
执行栈中的同步任务都执行完毕,栈内清空时,这个时候就回去任务队列中按顺序读取一个任务放入执行栈中执行,每次栈内清空,都会去读取任务队列有没有任务,有就读取执行,一直循环读取-执行的操作,就形成了事件循环。
-
定时器
定时器会开启一条定时器触发线程来触发计时,定时器会在等待了指定的时间后将事件放入到任务队列中等待读取到主线程执行。
setTimeout(函数,时间)、setInterval(函数,时间)。
定时器指定的延时毫秒数其实并不准确,因为定时器只是在到了指定的时间时将事件放入到任务队列中,必须要等到同步的任务和现有的任务队列中的事件全部执行完成之后,才会去读取定时器的事件到主线程执行,中间可能会存在耗时比较久的任务,那么就不可能保证在指定的时间执行。(定时器执行很快,但其中的函数属于异步任务,所以也会加入到任务队列之中)
-
宏任务、微任务
异步任务在同步任务之后,在异步任务中也是有先后之分的。异步任务可以分为宏任务和微任务。在执行任务时微任务是先于宏任务的。
宏任务(macrotask):setTimeout、setInterval、setImmediate、I/O、UI rendering
微任务(microtask):promise.then、process.nextTick