1.宏任务和微任务(笔试题)
常见的宏任务包含:
- 执行script标签内部代码、
- setTimeout/setInterval、
- ajax请、
- postMessageMessageChannel、
- setImmediate,
- I/O(Node.js)
常见的微任务包含:
- Promise.then(); Promise.cath()、
- async/await、
- process.nextTick(Node.js)、
- MutonObserver、
- Object.observe(异步监视对象修改,已废弃)、
- 加分回答 浏览器和Node 环境下,microtask 任务队列的执行时机不同 - Node端,microtask 在事件循环的各个阶段之间执行 - 浏览器端,microtask 在事件循环的 macrotask 执行完之后执行
注意:1.await之前的代码是同步里的,await执行后面的函数,然后返回一个promise,把await下面的代码放入微任务,并且退出这个async函数。
3.resolved后的promise对象会在这该级别事件队列结束之后才开始执行,及执行与该轮微任务队列中,始于下一级别宏任务之前
async function async1() {
console.log('async1 start') // 同步任务
await async2() // await要等右边全部执行完毕才会进行下一步
console.log('async1 end') // 微任务
}
async function async2() {
console.log('async2') // 同步任务
}
console.log('script start') // 同步任务
setTimeout(function () {
console.log('settimeout') // 宏任务
})
async1()
new Promise(function (resolve) {
console.log('promise1') // 同步任务
resolve()
}).then(function () {
console.log('promise2') // 微任务
})
console.log('script end') // 同步任务
执行结果
script start
async1 start
async2
promise1
script end
async1 end
promise2
settimeout
1.2.案例
setTimeout(() => {
console.log(1);
}, 0);
new Promise((resolve, reject) => {
console.log(2);
resolve("p1");
new Promise((resolve, reject) => {
console.log(3);
setTimeout(() => {
resolve("setTimeout2");
console.log(4);
}, 0);
resolve("p2");
}).then(data => {
console.log(data);
})
setTimeout(() => {
resolve("setTimeout1");
console.log(5);
}, 0);
}).then(data => {
console.log(data);
});
console.log(6);
执行结果
2 3 6 p2 p1 1 4 5
1.3.案例
console.log(11);
setTimeout(() => {
console.log(12);
let p = new Promise((resolve, reject) => {
resolve(13);
});
p.then(data => {
console.log(data);
});
console.log(15);
}, 0);
console.log(14);
执行结果
11 14 12 15 13
1.4 先执行 宏任务当中的同步任务 --> 微任务当中的同步任务 --> 微任务当中的异步任务 --> 宏任务中的异步任务
const handleClick = () => {
console.log('iop');
new Promise((resolve, reject) => {
console.log('promise-1');
setTimeout(() => {
console.log('promise-timeeout');
}, 0)
process.nextTick(function () {
console.log('promise---process.nextTick-1');
})
resolve('222')
}).then((res) => {
setTimeout(() => {
console.log('promise-then-timeout');
}, 0)
console.log('promise-then');
process.nextTick(function () {
console.log('promise.then---process.nextTick-1');
})
})
console.log('iop3333');
setTimeout(() => {
console.log('timeout-222');
}, 0)
process.nextTick(function () {
console.log('process.nextTick-1');
})
}
2.手写订阅发布模式
// 发布订阅中心, on-订阅, off取消订阅, emit发布, 内部需要一个单独事件中心caches进行存储;
interface CacheProps {
[key: string]: Array<((data?: unknown) => void)>;
}
class Observer {
private caches: CacheProps = {}; // 事件中心
on (eventName: string, fn: (data?: unknown) => void){ // eventName事件名-独一无二, fn订阅后执行的自定义行为
this.caches[eventName] = this.caches[eventName] || [];
this.caches[eventName].push(fn);
}
emit (eventName: string, data?: unknown) { // 发布 => 将订阅的事件进行统一执行
if (this.caches[eventName]) {
this.caches[eventName].forEach((fn: (data?: unknown) => void) => fn(data));
}
}
off (eventName: string, fn?: (data?: unknown) => void) { // 取消订阅 => 若fn不传, 直接取消该事件所有订阅信息
if (this.caches[eventName]) {
const newCaches = fn ? this.caches[eventName].filter(e => e !== fn) : [];
this.caches[eventName] = newCaches;
}
}
}
深入理解JavaScript宏任务与微任务:异步执行顺序与发布/订阅模式
本文详细解释了JavaScript中的宏任务和微任务执行机制,包括script标签、定时器、Promise和异步函数等的执行顺序,并通过案例演示。同时介绍了手写订阅发布模式在处理事件中的应用。
2570

被折叠的 条评论
为什么被折叠?



