js宏任务和微任务

本文深入探讨了JavaScript的运行机制,重点讲解了单线程、宏任务与微任务的概念。JavaScript在浏览器环境中是单线程的,以避免DOM操作的同步问题。任务队列分为宏任务队列和微任务队列,执行顺序为同步任务->微任务->宏任务。文章通过示例代码详细阐述了宏任务(如setTimeout)和微任务(如Promise)的执行流程,展示了任务的调度与执行顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0. 预备知识

JavaScript的运行机制:

  1. 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。

  2. 主线程之外,还存在"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。

  3. 一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。

  4. 主线程不断重复上面的第三步

概括即是: 调用栈中的同步任务都执行完毕,栈内被清空了,就代表主线程空闲了,这个时候就会去任务队列中按照顺序读取一个任务放入到栈中执行。每次栈内被清空,都会去读取任务队列有没有任务,有就读取执行,一直循环读取-执行的操作

一个事件循环中有一个或者是多个任务队列
JavaScript中有两种异步任务:

宏任务: script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering
微任务: process.nextTick(Nodejs), Promises, Object.observe, MutationObserver;

1、js为什么是单线程

什么是进程?
进程:是cpu分配资源的最小单位;(是能拥有资源和独立运行的最小单位)

什么是线程?
线程:是cpu调度的最小单位;(线程是建立在进程的基础上的一次程序运行单位,一个进程中可以有多个线程)

浏览器是多进程的
放在浏览器中,每打开一个tab页面,其实就是新开了一个进程,在这个进程中,还有ui渲染线程,js引擎线程,http请求线程等。 所以,浏览器是一个多进程的。

大家都在说js是单线程的,但是为什么要设计成单线程?
这主要和js的用途有关,js是作为浏览器的脚本语言,主要是实现用户与浏览器的交互,以及操作dom;这决定了它只能是单线程,否则会带来很复杂的同步问题。 举个例子:如果js被设计了多线程,如果有一个线程要修改一个dom元素,另一个线程要删除这个dom元素,此时浏览器就会一脸茫然,不知所措。所以,为了避免复杂性,从一诞生,JavaScript就是单线程,这已经成了这门语言的核心特征,将来也不会改变

2、js宏任务和微任务

在这里插入图片描述

//执行顺序
同步(Promise)>异步(微任务(process.nextTick ,Promises.then, Promise.catch ,resove,
reject,MutationObserver)>宏认为(setTimeout,setInterval,setImmediate))

process.nextTick> Promises.then

在挂起任务时,JS 引擎会将所有任务按照类别分到这两个队列中,首先在 macrotask 的队列(这个队列也被叫做 task queue)中取出第一个任务,执行完毕后取出 microtask 队列中的所有任务顺序执行;之后再取 macrotask 任务,周而复始,直至两个队列的任务都取完
在这里插入图片描述
宏任务和微任务之间的关系
在这里插入图片描述

//主线程直接执行

console.log('1');

//丢到宏事件队列中

setTimeout(function() {

    console.log('2');

    process.nextTick(function() {

        console.log('3');

    })

	// new一个Promise对象是同步任务,Promise中then,catch等方法是异步微任务
    new Promise(function(resolve) {

        console.log('4');

        resolve();

    }).then(function() {

        console.log('5')

    })

})

//微事件1

process.nextTick(function() {

    console.log('6');

})

//主线程直接执行

new Promise(function(resolve) {

    console.log('7');

    resolve();

}).then(function() {

    //微事件2

    console.log('8')

})

//丢到宏事件队列中

setTimeout(function() {

    console.log('9');

    process.nextTick(function() {

        console.log('10');

    })

    new Promise(function(resolve) {

        console.log('11');

        resolve();

    }).then(function() {

        console.log('12')

    })

})

当js被执行时,就是开启一个宏任务,在宏任务中执行指令。
输出结果:1 7 6 8 2 4 3 5 9 11 10 12

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值