通俗的将单线程就是同一个时间内只做一件事,这样的好处就是避免 DOM 渲染冲突。而异步则是对页面渲染阻塞的解决方案,要想彻底搞懂异步,我们首先要对异步的执行过程进行了解,即事件循环机制
请看原文:https://juejin.im/post/59e85eebf265da430d571f89
不同的任务源会被分配到不同的 Task队列中,任务源可以分为微任务(microtask)和宏任务(macrotask)。在 ES6 规范中,microtask 称为 jobs,macrotask 称为 task.
下面配上原文图:
==微任务包括:== process.nextTick,promise,DOM 发生变化、MutationObserver。 ==宏任务包括:== 包括整体代码 script,setTimeout,setInterval,setImmediate,I/O,UI rendering.
事件循环顺序: js 引擎 --> 清空微任务 --> UI 渲染 --> 取出宏任务 --> js 引擎执行
*: js 引擎即执行栈包含同步任务与异步任务。
原文地址: https://github.com/SunShinewyf/issue-blog/issues/34#issuecomment-371106502
首先它不会立即执行。它是指定某个任务在主线程最早可得的空闲时间执行,意思就是不用再等多少秒了,只要主线程执行栈内的同步任务全部执行完成,栈为空就马上执行
console.log('开始执行');setTimeout(() => {console.log('setTimeout');}, 0);console.log('执行完成');
开始执行执行完成 setTimeout
setTimeout(fn,0)在 timer 阶段执行,并且是在 poll 阶段进行判断是否达到指定的 time 时间才会执行
setImmediate 在 check 阶段才会执行两者的执行顺序要根据当前的执行环境才能确定,根据官方文档总结得出的结论是:
如果两者都在主模块(main module)调用,那么执行先后取决于进程性能,即随机。
如果两者都不在主模块调用(即在一个 IO circle 中调用),那么 setImmediate 的回调永远先执行。
/*** 首先 setTimeout(fn,0)===setTimeout(fn,1)* 如果进入事件循环所花费的大于1ms时间,那么timer阶段会直接执行setTimeout* 如果准备时间花费小于1ms,那么setImmediate回调先执行*/setTimeout(() => {console.log('setTimeout');}, 0);setImmediate(() => {console.log('setImmediate');});
IO circle 中调用,那么 setImmediate 的回调永远先执行
const fs = require('fs');fs.readFile(__filename, () => {setTimeout(() => {console.log('timeout');}, 0);setImmediate(() => {console.log('immediate');});});
**声明:**本文都是摘抄网上一些好的文章,杂合而成,如何侵权请留言 优秀原文: Tasks, microtasks, queues and schedules