1、js单线程,并非指js只有一个线程,而是同一时刻只能有一个线程在工作。

2、js中,主线程之外,还有其余线程,比方事件循环线程,定时器触发线程,http异步线程, 浏览器事件线程。

3、在js主线程中,分为两个子线程,js引擎线程,GUI渲染线程。这两个线程是互斥的,同一时刻只能执行一个,要么执行js,要么渲染html

4、工作队列中,分为宏工作微工作。每次执行工作队列时,先执行微工作,再执行宏工作。

5、通常宏工作指 setTimeout,setInterval,XMLHttprequest,fetch等回调。 微工作指 Promise,MutationObserver等回调。

6、如果在 定时器触发线程、http异步线程、浏览器事件线程中,没有回调,则不会放入队列中。

7、事件循环线程,必须期待主线程中的同步代码执行完结,才会去工作队列再取一个 工作放入 主线程中执行。

//index.jsconsole.log('a');  Promise.resolve().then(() => {    console.log('b');  });  setTimeout(() => {    console.log('c');  }, 0);  setTimeout(() => {    console.log('d');    Promise.resolve().then(() => {      console.log('e');    });  }, 0);  console.log('f');

上面是上述代码的执行逻辑:

  1. 遇到console.log('a'); 同步代码,执行,输入a;
  2. 遇到Promise,异步代码,放入工作队列。又因为是promise的回调,属于微工作。标记微工作1
  3. 遇到setTimeout执行,放入定制器触发线程中,定时器触发线程中保护何时倒计时完结,并将回调放入工作队列。又因为setTimeout的回调属于宏工作。标记为宏工作1
  4. 又遇到setTimeout执行,放入定制器触发线程中,将回调放入工作队列。因为setTimeout的回调属于宏工作。标记为宏工作2
  5. 遇到console.log('f'); 同步代码,执行,输入f

此时主线程中的同步代码曾经齐全执行,控制台输入a,f。主线程是空的。此时事件循环线程发现,工作队列有货色,别离是微工作1,宏工作1,宏工作2.

  1. 依照先执行微工作,再执行宏工作程序,先将微工作1,即 () => { console.log('b'); } 放入主线程中由js执行。输入b,
  2. 此时主线程执行完,又空了,此时工作队列还有宏工作1,宏工作2。因为宏工作1先放入的,依照队列的先进先出程序。先将宏工作1放入主线程。即 () => { console.log('c'); },输入c,
  3. 再判断队列中是否有微工作,如果有,则全副执行。如果没有,就继续执行宏工作2.
  4. 将宏工作2放入主线程,即

    () => { console.log('d'); Promise.resolve().then(() => {   console.log('e'); });}

    输入d,遇到promise,异步代码,放入微工作队列。标记为微工作2。此时主线程又空了。

  5. 此时工作队列只有微工作2,没有其余的宏工作和微工作。 最初再执行微工作2。即 () => { console.log('e'); }, 输入e

总结下: 最初输入后果为 a f b c d e

留神:
1、下面的 setTimeout(()=>{}); 属于同步代码,会执行,如果 let timer = setTimeout(()=>{}); 你会发现timer有值,是个数字。但也仅仅是执行 setTimeout后将援用返回,剩下的倒计时和回调。都在定时器触发线程中保护。
2、同样,下面的 Promise.resolve() 也属于同步代码,let p = Promise.resolve() .会发现p有值,是个Promise对象,但也仅仅是执行 Promise.resolve() 后将援用返回,剩下的then中的回调。都在微工作队列中保护

以上是本人通过浏览其余文章,加上本人了解和本地调试之后的 一点点感想。 如有问题,还望斧正。