# JS运行机制

  • https://juejin.im/post/6844904040841609223

# JS为啥是单线程?

    1. JS是单线程的,即JS在同一时间只能做一件事
  • js作为浏览器脚本语言,其主要用途是与用户互动,以及操作DOM。这就决定了它只能是单线程,否则会带来很复杂的同步问题。(假设JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?)

# JS同步任务和异步任务

  • JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。如果前一个任务耗时很长,后一个任务就不得不一直等着。JavaScript语言的设计者意识到这个问题,将所有任务分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)
  • 同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
  • 异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行

# 任务队列(消息队列)

  • 任务队列中存着的是异步任务,这些异步任务一定要等到执行栈清空后才会执行。 异步任务,会先到事件列表中注册回调函数。如果事件列表中的事件触发了,会将这个回调函数移入到任务队列中(DOM操作对应DOM事件,资源加载操作对应加载事件,定时器操作可以看做对应一个“时间到了”的事件)

# 宏任务与微任务

  • macro-task(宏任务):包括整体代码script,setTimeout,setInterval, setImmediate, I/O, UI rendering
  • micro-task(微任务):Promise,process.nextTick,MutationObserver
  • 微任务意义:
    • 减少更新时的渲染次数。因为根据HTML标准,会在宏任务执行结束之后,在下一个宏任务开始执行之前,UI都会重新渲染。如果在microtask中就完成数据更新,当 macro-task结束就可以得到最新的UI了。如果新建一个 macro-task来做数据更新的话,那么渲染会执行两次

# Event Loop(事件循环)

  • https://www.jianshu.com/p/a05dd3ac0150
  • 1.整体的script(作为第一个宏任务)开始执行的时候,会把所有代码分为两部分:“同步任务”、“异步任务”;
  • 2.同步任务会直接进入主线程依次执行;
  • 3.异步任务会再分为宏任务和微任务;
  • 4.宏任务进入到Event Table中,并在里面注册回调函数,每当指定的事件完成时,Event Table会将这个函数移到Event Queue中;
  • 5.微任务也会进入到另一个Event Table中,并在里面注册回调函数,每当指定的事件完成时,Event Table会将这个函数移到Event Queue中;
  • 6.当主线程内的任务执行完毕,主线程为空时,会检查微任务的Event Queue,如果有任务,就全部执行,如果没有就执行下一个宏任务;
  • 7.上述过程会不断重复,这就是Event Loop事件循环;

#

  • 事件循环就是Event Loop,执行栈和任务队列是JavaScript 执行异步任务的管理方式,宏任务和微任务是js异步任务更细粒度的划分。
  • 总结JavaScript处理同步异步任务的方式是:用栈和队列调度分配任务,代码首次运行主线程按照同步任务顺序,依次执行,执行期间产生的异步宏任务则挂起不执行,挂起的方式是添加至宏任务执行队列,产生的微任务也挂起,方式是添加至微任务执行队列。待所有同步任务执行完成,主线程从宏任务执行队列取出最先添加进宏任务执行队列的任务,放入执行栈执行,执行完后立即去执行所有的微任务,微任务清空后再执行下一个宏任务,每执行完一个宏任务就去清空一下微任务,直到两个执行队列全清空。如此循环就是Event Loop事件循环。