首页 前端知识 js 的宏任务和微任务

js 的宏任务和微任务

2025-03-13 15:03:07 前端知识 前端哥 807 16 我要收藏

宏任务 (macro-task) 与微任务 (micro-task)

在 JavaScript 中,宏任务(macro-task)和微任务(micro-task)是任务队列(task queue)中两个不同的任务类型,它们是 JavaScript 异步编程机制的重要组成部分。

事件循环(Event Loop)是 JavaScript 中处理异步操作的机制,它确保代码按预期顺序执行,同时保持 js 单线程的特性。事件循环不断检查任务队列,按照一定规则处理同步代码、宏任务和微任务,并决定何时执行它们。

宏任务是事件循环中的主要任务队列;宏任务会在每轮事件循环中依次执行,执行完一个宏任务后,事件循环会检查是否有需要执行的微任务队列。常见的宏任务:主代码块(script)、setTimeout、setInterval、I/O 操作、UI rendering。

微任务优先级更高,它会在当前宏任务执行完后立即执行,并在下一个宏任务开始前完成。微任务可以在不等到下一轮事件循环的情况下进行。常见的微任务:Promise.then / Promise.catch / Promise.finally、MutationObserver、queueMicrotask。

注意:当 new Promise 时,此时视为宏任务的状态。当 resolvereject 时,把它们加入到微任务队列中,例如练习 2。
总结:事件循环每次迭代会执行一个宏任务的所有脚本,然后处理所有微任务。

执行顺序:
① JavaScript 先执行当前宏任务中的同步代码;
② 如果执行过程中遇到微任务,它会被加入微任务队列,但不会立即执行;
③ 当前宏任务中的所有同步代码执行完毕后,会执行微任务队列中的所有微任务,直到队列为空;
④ 微任务队列清空后,事件循环将继续执行下一个宏任务。

console.log('宏任务开始');  // 同步代码,立即执行

setTimeout(() => {
  console.log('宏任务:setTimeout');  // 宏任务
}, 0);

Promise.resolve().then(() => {
  console.log('微任务:Promise 1');  // 微任务
}).then(() => {
  console.log('微任务:Promise 2');  // 微任务
});

console.log('宏任务结束');  // 同步代码,立即执行

按照上面的内容,分析执行步骤:

  1. 宏任务:执行整体代码(相当于 <script> 中的代码):
    输出:宏任务开始
    遇到 setTimeout,加入宏任务队列,当前宏任务队列 [setTimeout]
    遇到 Promise.resolve().then(),加入微任务,当前微任务队列 [promise1]
    输出:宏任务结束

  2. 微任务:执行微任务队列 [promise1]
    输出:微任务:promise1
    遇到 then,加入微任务队列,当前微任务队列 [then()]
    【微任务队列中不为空】执行微任务队列 [then()],输出:微任务:promise2

  3. 执行渲染操作,更新界面(敲黑板划重点)。

  4. 宏任务:执行 setTimeout
    输出:宏任务:setTimeout

练习

在线运行 JavaScript ,在这个网站上输出下方练习的结果。
要就来45道Promise面试题一次爽到底 这里有更多的关于 Promise 的面试题。

练习 1

const promise1 = new Promise((resolve, reject) => {
  console.log('promise1')
})
console.log('1', promise1);

练习 2

const promise = new Promise((resolve, reject) => {
  console.log(1);
  resolve('success')
  console.log(2);
});
promise.then(() => {
  console.log(3);
});
console.log(4);

练习 3

const promise = new Promise((resolve, reject) => {
  console.log(1);
  console.log(2); 
});
promise.then(() => {  
  console.log(3);
});
console.log(4);

练习 4

const fn = () =>
  new Promise((resolve, reject) => {
    console.log(1);
    resolve("success");
  });
console.log("start"); 
fn().then(res => {
  console.log(res);
});

练习 5

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");

练习 6:

const promise = new Promise((resolve, reject) => {
  console.log(1);
  setTimeout(() => {
    console.log("timerStart");
    resolve("success");
    console.log("timerEnd");
  }, 0);
  console.log(2);
});
promise.then((res) => {
  console.log(res);
});
console.log(4);

练习 7

setTimeout(() => {
  console.log('timer1');
  Promise.resolve().then(() => {
    console.log('promise')
  })
}, 0)
setTimeout(() => {
  console.log('timer2')
}, 0)
console.log('start')

练习 8

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('success')
  }, 1000)
})
const promise2 = promise1.then(() => {
  throw new Error('error!!!')
})
console.log('promise1', promise1)
console.log('promise2', promise2)
setTimeout(() => {
  console.log('promise1', promise1)
  console.log('promise2', promise2)
}, 2000)
运行结果

练习 1:

promise1
1 Promise {<pending>}

练习 2

1 
2 
4 
3

练习 3:
这里 promise.then() 不会执行

1 
2 
4

练习 4
这里 fn 函数包裹着 new Promise,因此只有当 fn 被调用时,里面的 new Promise 才会被执行。

start
1
success

练习 5

script start
script end
promise1
promise2
setTimeout

练习 6:
① 从上到下同步完后,微任务队列并没有任务,而宏任务队列有一个 setTimeout,因此下一个执行宏任务队列里的任务;
② 当完成执行完 setTimeout,微任务队列里存在 Promise.then()
③ 执行 Promise.then() 的内容。

1
2
4
timerStart
timerEnd
success

练习 7
① 同步整个代码后,宏任务队列里面含有第一个 setTimeout 和第二个 setTimeout,而微任务队列里为空;
② 取出第一个 setTimeout,然后执行代码。执行完成后,微任务队列新增了一个 Promise.then
③ 执行 Promise.then
④ 执行第二个 setTimeout

start
timer1
promise
timer2

练习 8
考察 Promise 的三种状态。

'promise1' Promise{<pending>}
'promise2' Promise{<pending>}
test5.html:102 Uncaught (in promise) Error: error!!! at test.html:102
'promise1' Promise{<resolved>: "success"}
'promise2' Promise{<rejected>: Error: error!!!}

在这里插入图片描述

转载请注明出处或者链接地址:https://www.qianduange.cn//article/23475.html
标签
评论
会员中心 联系我 留言建议 回顶部
复制成功!