一、Js为什么需要有任务队列机制?
因为js是个单线程的程序机制,没有什么多线程。如果有多线程,比如说,一个线程在操作一个dom节点,然后另一个线程也去操作同一个dom节点,这样就会发生跟数据库中有关锁的内容类似的东西–数据库中就是因为避免同时处理某个数据才出现锁的相关内容。避免这种麻烦,因此,js是单线程机制。
二、js的任务队列是什么运行机制
首先,如果js只是单纯的单线程机制,那么像定时器这些程序就很难实现,因为如果是单纯的单线程,如果执行到定时器,那么就会暂停然后执行下面的程序,js显然不是这样的,它是先跳过定时器执行下面,然后过了相应的时间之后再把定时器里面的代码拿出来执行,这就更像一个双线程的运行逻辑,但是在js中,这是异步执行块。
在js中将js的任务分为同步任务与异步任务。同步任务是主线程,异步任务是指耗时程序,例如定时器和ajax请求等。如下图所示,异步任务又可以分为宏任务和微任务。其中,宏任务包括setTimeout定时器和setInterval计时器等;微任务包括promise中的各种回调函数等。
那么,js的运行机制是怎么样的?
我的理解如上图所示,js等任务队列有三个,一个是主线程任务队列,这个对应的是按照你写代码的顺序执行,也没什么队列了就是读取一条执行一条;第二个是异步任务队列中的宏任务队列,这里面包含的是定时器、计时器、IO操作以及UI渲染等;第三个是微任务队列,这里面包含的是promise的各种回调函数。
异步任务执行完成,回调函数等到可以执行的时候就按照分类放入异步队列中,当主线程中当前任务执行完毕,就去查看是否有异步任务需要执行,异步任务中微任务的执行优先级高于宏任务,先将微任务执行完再执行宏任务。整个流程如下图所示。
三、举例说明
<script>
Promise.resolve("3333").then((res) => { //微任务
console.log("Promise输出" + res);
setTimeout(() => { //微任务里面的宏任务
console.log("Promise中的setTimeout输出");
});
});
setTimeout(() => { //宏任务
console.log("setTimeout输出!");
Promise.resolve("4444").then((res) => { //宏任务里面的微任务
console.log("setTimeout中的Promise输出" + res);
});
}, 0);
console.log("主线程输出1");
</script>
看结果可知,它先执行主线程程序,然后执行微任务,再执行宏任务再执行宏任务里的微任务,最后执行微任务里的宏任务。