模拟微任务的实现
- 微任务的模拟实现 queueMicrotask 、MutationObserver、setImmediate【该特性是非标准的,不要在生产环境中使用它】、setTimeout兜底
- 我们选用 queueMicrotask 、MutationObserver、setTimeout。考虑到兼容性,setTimeout兜底
console.log("1");
queueMicrotask(() => {
console.log("queueMicrotask");
});
console.log("2");
console.log("1");
const obs = new MutationObserver(() => {
console.log("MutationObserver");
});
const divNode = document.createElement("div");
obs.observe(divNode, { childList: true });
divNode.innerText = "itheima 666";
console.log("2");
实现Promise的微任务
<script>
function runAsyncTask(callback) {
if (typeof queueMicrotask === "function") {
queueMicrotask(callback);
} else if (typeof MutationObserver === "function") {
const obs = new MutationObserver(callback);
const divNode = document.createElement("div");
obs.observe(divNode, { childList: true });
divNode.innerText = "fx666";
} else {
setTimeout(callback, 0);
}
}
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class FXPromise {
state = PENDING;
result = undefined;
#handlers = [];
constructor(fn) {
const resolve = (res) => {
if (this.state === PENDING) {
this.result = res;
this.state = FULFILLED;
this.#handlers.forEach(({ onFulfilled }) => {
onFulfilled(this.result);
});
}
};
const rejectFunc = (res) => {
if (this.state === PENDING) {
this.result = res;
this.state = REJECTED;
this.#handlers.forEach(({ onRejected }) => onRejected(this.result));
}
};
fn(resolve, rejectFunc);
}
then(onFulfilled, onRejected) {
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (x) => x;
onRejected =
typeof onRejected === "function"
? onRejected
: (x) => {
throw x;
};
if (this.state === FULFILLED) {
runAsyncTask(() => {
onFulfilled(this.result);
});
} else if (this.state === REJECTED) {
runAsyncTask(() => {
onRejected(this.result);
});
} else if (this.state === PENDING) {
this.#handlers.push({
onFulfilled: (res) => {
runAsyncTask(() => {
onFulfilled(res);
});
},
onRejected: (res) => {
runAsyncTask(() => {
onRejected(res);
});
},
});
}
}
}
console.log(1);
const p = new FXPromise((resolve, reject) => {
resolve("resolve");
});
p.then(
(res) => {
console.log("then res ", res);
},
(err) => {
console.log("then err ", err);
}
);
console.log(2);
</script>
