JS异步编程

  • 为什么JS需要异步?

    JS语言设计之初,是为了能够操作浏览器DOM元素,为避免两个线程同时操作某DOM元素导致DOM元素显示结果异常,JS被设计为一个单线程的语言。

    • 如何理解单线程?

      这里所谓的单线程,指的是JS的执行线程只有一个,而不是指JS引擎所占用的CPU线程,JS的内部API(EventLoop,消息队列等)需要更多的CPU线程协助JS执行线程正确处理。

      举例说明,很多人去银行办理业务,窗口只有一个,同时只能有一个人办理业务,但是可能会需要一个大堂经理来协助大家排队,通知该到谁去办理业务。这里边的单一窗口就是意味着单一线程,而大堂经理,就类似于消息队列,无疑需要耗费额外的CPU线程。

    • 为何单线程就需要异步

      当执行耗时操作时,后边的代码将全部被阻塞,反应到浏览器上,就会发现浏览器被卡死,为避免此种情况发生,耗时的操作就会被丢到异步任务中去处理。

      举例说明:现在客户A办理的业务是开户,需要填写很多资料,只能先退出队伍填写资料后,再回来处理相应的后续业务。

  • JS如何处理异步

    借助EventLoop和消息队列:每一个异步任务在结束后,会被放到消息队列中排队,EventLoop在每次主线程的同步任务(宏任务及其附属的微任务)结束之后,会不断遍历消息队列,按照消息队列的入队顺序处理接下来的任务。

    • 什么是EventLoop和消息队列?

      消息队列就是存储已完成的异步任务的回调队列,而EventLoop是一种消费消息队列的机制,这种机制上文有说明。

      举例说明:现在办理业务的一共有10个人,前三个人A,B,C办理开户,需要额外填写资料,后7人办理取款,很快就能完成。于是,异步任务产生了。A,B,C去开户时,会被要求填写资料,然后就轮到后边取款的人办理业务。如果ABC有人填写完资料,就会到旁边再起一队,当另7个人的业务完成后,会过来一名叫号员,把新队伍里排在最前边的人领到窗口,继续为其办理开户。这里新起的一队,就是消息队列,而在任务都完成后过来的叫号员,就是EventLoop了。

    • 什么是宏任务和微任务?

      宏任务:同步代码,setTimeout,setInterval,requestAnimationFrame,setImmediate
      微任务:proccess.nextTick,Promise,MutationObserver

      很多文章单纯的说微任务先执行,宏任务后执行,所以Promise中的console会先于setTimeout中的console先输出出来,这种说法是极为不准确的。
      这里准确地说一下宏任务和微任务的执行机制:每一个微任务,都附属在一个宏任务上,当宏任务执行完毕后,会执行该宏任务下对应的所有微任务。Promise先于setTimeout执行的根本原因是,这个Promise是产生在同步代码中,所以这个微任务是附属在同步代码这个宏任务上的,而setTimeout相当于另一个宏任务,所以要在同步代码的微任务结束后才会执行。

你可能感兴趣的:(JS异步编程)