JS任务机制初解

114 阅读2分钟

微任务_宏任务

代码

下面可执行代码, 按什么顺序执行呢?

同步_异步

同步代码: 执行顺序和书写顺序一致

异步代码: 不是立即执行的,执行顺序和书写顺序不一致。

js中典型的异步代码有:

  • 定时器:setTimeout,setInterval
  • Ajax
  • dom事件 但实际上, js是一门单线程语言, 他是怎么实现异步的呢?

事件循环Event Loop

js是单线程的,一次只能做一件事。js在浏览器这个宿主环境中运行。浏览器是多线程的,用户交互,定时器,网络请求等等浏览器中的事件会产生对应的任务,任务多了要在任务队列中排队,浏览器的主线程依次取出任务来执行,此过程不断重复从而形成一个循环,称为eventLoop。

微任务_宏任务

异步任务也有优先级区分,优先级高的叫微任务,相对低的是宏任务 不是马上执行,是放入到队列中等待;

如果所有的任务都要按序等待,那么也不行,需要有一个能插队的机制。所以又将异步任务分为微任务和宏任务,同时对应微任务队列和宏任务队列。

当主线程空闲时,先执行微任务队列中的任务,再去执行宏任务队列中的任务。

微任务代码(js语法)

  • Promise对象.then()

宏任务代码(宿主环境)

  • script
  • dom事件
  • ajax
  • setTimout

示例

<script>
    1 console.log(1);
    2 async function fnOne() {
        console.log(2);
        await fnTwo(); 
        console.log(3);
    }
    3 async function fnTwo() {
        console.log(4);
    }
    4 fnOne(); 
    5 setTimeout(() => {
        console.log(5);
    }, 2000); 
    6 let p = new Promise((resolve, reject) => {
        console.log(6);
        resolve();
        console.log(7);
    }) 
    7 setTimeout(() => {
        console.log(8)
    }, 0) 
    8 p.then(() => {
        console.log(9);
    }) 
    9 console.log(10); 
</script>

分析:

a. script首当其冲,进入宏任务队列.开始执行script内代码.

b. 1行同步代码直接打印1 =>

2行代码为函数定义,不执行 =>

3行也是定义 => 4行开始执行fnOne函数 =>

进入2行,打印2,await fnTwo()执行fnTwo,进入3,打印4,由于await阻塞了当前函数的下面代码块运行, 所以console.log(3)放入微任务队列 =>

5行 放入宏任务 =>

6行 new 关键字同步执行,打印6,返回fullfilled状态的promise对象,值undefined, 打印7 =>

7行放入宏任务队列,但他是0s后执行,比5定时器快,所以排在前面 =>

8行 因为p上面得状态fullfilled,所以then执行,放入微任务队列 =>

9行 打印10

***b结果:结果:1 2 4 6 7 10 ***

c. 上面script的宏任务已经完成

(右边优先)

微任务队列有: log(9) log(3)

宏任务队列有: log(5) 2s log(8) 0s

先执行微任务队列, 随后执行宏任务队列 输出:3 9 8 5

最终打印结果为: 1 2 4 6 7 10 3 9 8 5