事件循环(搞懂异步各任务的执行顺序)

Posted 鹿鹿想学编程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了事件循环(搞懂异步各任务的执行顺序)相关的知识,希望对你有一定的参考价值。

在说我们的事件循环之前我们需要先知道这两个概念:
1、什么是同步和异步
2、JS异步是怎么实现的

首先同步和异步。其实这个很很好理解,同步其实就是代码按照我们的编写顺序执行,那么异步呢其实就是代码的执行顺序可能会和我们的编写顺序不一样

JS异步是怎么实现的?
我们都知道JS是单线程执行语言,其实单线程指的是JS的主运行线程只有一个,并不是说整个运行环境都是单线程的。JS的运行环境主要是浏览器,那么我们的浏览器内核(比如chrome)不仅仅是多线程的还是多进程的
所以JS异步的实现靠的就是浏览器的多线程,当他遇到异步API时,就将这个任务交给对应的线程,当这个异步API满足回调条件时,对应的线程又通过事件触发线程将这个事件放入任务队列,然后主线程从任务队列取出事件继续执行。这个流程我们多次提到了任务队列,这其实就是Event Loop

其实这个event loop就是我们要讲的事件循环
我们先理解一下下面这个图

那么什么是宏任务和微任务呢
规范中规定,task分为两大类, 分别是 Macro Task (宏任务)和 Micro Task(微任务), 并且每个宏任务结束后, 都要清空所有的微任务,这里的 Macro Task也是我们常说的 task ,有些文章并没有对其做区分

宏任务主要包含:script( 整体代码)、setTimeout、setInterval、I/O、UI 交互事件、setImmediate(Node.js 环境)
微任务主要包含:Promise、MutaionObserver、process.nextTick(Node.js 环境)
setTimeout/Promise 等API便是任务源,而进入任务队列的是由他们指定的具体执行任务。来自不同任务源的任务会进入到不同的任务队列。其中 setTimeout 与 setInterval 是同源的。

那么我们的代码在运行的时候,是先执行一个宏任务再清空微任务,这样执行,那么其实任务中也有执行的优先级,比如说这里process.nextTick这个的优先级就是最高的,然后setImmediate的优先级也会比
setTimeout(fn,0)高,但是具体为什么这个就需要看我们JS的底层原理了,这里就先不述说了。

举几个例子吧!

 console.log('script start');
        setTimeout(function() {
          console.log('setTimeout');
        }, 0);
        
        Promise.resolve().then(function() {
          console.log('promise1');
        }).then(function() {
          console.log('promise2');
        });
        console.log('script end');

很明显这个没有转弯大家就可以直接写出答案

start end promise1  promise2 setTimeout 

再来一个在node环境下运行的例子

function timer() {
    setTimeout(()=>{
        console.log(1);
    },0)
    setImmediate(()=>{
        console.log(2);
    })
    console.log(3);
    process.nextTick(()=>{
        console.log(4);
    })
}

那么就像我们刚刚说的那样,这次的输出结果是

那么通过这两个例子,大家估计也对我们的事件循环有了很清晰的认识啦!!!

以上是关于事件循环(搞懂异步各任务的执行顺序)的主要内容,如果未能解决你的问题,请参考以下文章

事件循环(event loop)

异步编程之事件循环机制

nodejs所用的概念(同步,异步,事件驱动,事件循环等)通俗解释

js事件循环运行机制

js事件循环运行机制

解决for循环中异步请求顺序不一致的问题