为什么script 标签是一个宏任务
JS 是一门单线程的语言,因此,JS 在同一时间只能做一件事,单线程意味着,如果在同个时间有多个任务,这些任务就要排队,前一个任务执行完,才会执行下一个任务。
举个栗子:
<!-- 脚本 1 --> |
结果:
script A |
步骤:
- 最开始,JS 引擎将这段代码解析成两个宏任务,一个是 脚本 1,一个是 脚本 2。会把这两个宏任务放到宏任务队列中去。正常情况下,JS 执行是先微后宏,此时微任务队列中没有队列任务,就跳过,去执行宏任务。
- 因为 脚本 1 在上面,JS 会去先执行 脚本 1 ,然后就把 script A 压入 【调用栈】中。
- 由于第一行代码是同步代码,所以先执行。
- 将 timer1 压入 宏任务队列中
- new Promise() 中 p1 是 同步任务,立即执行,出栈
- 触发异步机制,进入 Promise.then() 中,触发回调,把 A3 加入微任务队列中去,等待执行
- 此时,按照“先微后宏“的顺序, 此时,微任务队列中有任务,就把 A3 放入调用栈中执行,输出 A3,出栈(A4 是同步代码,已经在 A3 之前执行输出)
此时,微任务队列中没有任务了,事件循环会跳过微任务,去执行宏任务。会把 script B 调入调用栈中去(不是全部一下子调入调用栈中的,是按照代码先后顺序去逐行调入的)。
- 将 B1 这个宏任务加入到宏任务队列中去
- B2 是同步代码,加入调用栈中,执行,输出, 出栈;输出 B4,scriptB 宏任务就结束了,调用栈清空。
- 触发异步回调 Promise.then(),将 B3 加入到微任务队列中去。
- 此时,如图 6,按照先微后宏的顺序,会依次把 B3、A1、B1 输出。