手写Promise(node版)
Opened this issue · 0 comments
chunhuigao commented
const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
class Promise {
constructor(executor) {
if (typeof executor !== "function") {
return new TypeError(`Promise resolver ${executor} is not a function`);
}
this.state = PENDING;
this.value = null;
this.reason = null;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLED;
this.value = value;
this.onFulfilledCallbacks.forEach((fn) => fn());
}
};
const reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED;
this.reason = reason;
this.onRejectedCallbacks.forEach((fn) => fn());
}
};
try {
executor(resolve, reject);
} catch (e) {
this.reject(e);
}
}
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== "function") {
onFulfilled = (value) => value;
}
if (typeof onRejected !== "function") {
onRejected = (err) => {
throw err;
};
}
let promise2 = new Promise((resolve, reject) => {
if (this.state === FULFILLED) {
process.nextTick(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
if (this.state === REJECTED) {
process.nextTick(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
process.nextTick(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
this.onRejectedCallbacks.push(() => {
process.nextTick(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
});
return promise2;
}
}
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x)
return reject(
new TypeError("Chaining cycle detected for promise #<Promise>")
);
if ((typeof x === "object" && x !== null) || typeof x === "function") {
let called;
try {
const then = x.then;
if (typeof then !== "function") resolve(x);
else {
then.call(
x,
(value) => {
if (called) return;
called = true;
resolvePromise(promise2, value, resolve, reject);
},
(reason) => {
if (called) return;
called = true;
reject(reason);
}
);
}
} catch (err) {
if (called) return;
called = true;
reject(err);
}
} else {
resolve(x);
}
};