手写JS Promise函数
const STATE = {
PENDING: "pending",
FULFILLED: "fulfilled",
REJECTED: "rejected",
};
function isPromise(obj) {
return !!(
obj &&
typeof obj === "object" &&
obj.then &&
typeof obj.then === "function"
);
}
function runMicroHandler(callback) {
if (process && process.nextTick) {
process.nextTick(callback);
}
else if (MutationObserver) {
const p = document.createElement("p");
const observer = new MutationObserver(callback);
observer.observe(p, { childList: true });
p.innerHtml = "1";
} else {
setTimeout(callback, 0);
}
}
class MyPromise {
constructor(executor) {
this._value = null;
this._state = STATE.PENDING;
this._handlers = [];
try {
executor(this._resolve.bind(this), this._reject.bind(this));
} catch (error) {
this._changeState(error, STATE.REJECTED);
}
}
_pushHandler(handler, state, resolve, reject) {
this._handlers.push({ executor: handler, state, resolve, reject });
}
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
this._pushHandler(onFulfilled, STATE.FULFILLED, resolve, reject);
this._pushHandler(onRejected, STATE.REJECTED, resolve, reject);
this._runHandlers();
});
}
_runOneHandler(handler) {
runMicroHandler(() => {
if (this._state !== handler.state) return;
if (typeof handler.executor !== "function") {
handler.resolve(this._value);
return;
}
try {
const res = handler.executor(this._value);
if (isPromise(res)) {
res.then(handler.resolve, handler.reject);
}
handler.resolve(res);
} catch (error) {
handler.reject(error);
}
});
}
_runHandlers() {
if (this._state === STATE.PENDING) return;
while (this._handlers[0]) {
this._runOneHandler(this._handlers[0]);
this._handlers.shift();
}
}
_changeState(value, state) {
if (this._state !== STATE.PENDING) return;
this._value = value;
this._state = state;
this._runHandlers();
}
_resolve(value) {
this._changeState(value, STATE.FULFILLED);
}
_reject(err) {
this._changeState(err, STATE.REJECTED);
}
}
const p = new MyPromise((resolve, reject) => {
resolve(123);
reject(456);
});
const p1 = new MyPromise((resolve) => {
resolve(123);
});
const p2 = p1.then(
(res) => {
return res;
},
(err) => {},
);
const p3 = p2.then((res) => {
return new MyPromise((resolve) => {
resolve(res);
});
});
const p4 = p3.then(123);
console.log("p", p);
console.log("p1", p1);
setTimeout(() => {
console.log("p2", p2);
}, 10);
setTimeout(() => {
console.log("p3", p3);
}, 20);
setTimeout(() => {
console.log("p4", p4);
}, 30);