-
-
Notifications
You must be signed in to change notification settings - Fork 235
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
8. 完整实现Promise A+ #8
Comments
class myPromise {
} |
Promise A+规范要求obj是一个对象或函数,这样写是否是更合理一点 function isPromise(obj) {
return !!(obj && (typeof obj === "object" || typeof obj === 'function') && typeof obj.then === "function");
} |
请问这两边都需要执行队列中的函数吗?有点没太明白
和
|
This comment was marked as abuse.
This comment was marked as abuse.
function Promise(executor) {
this.state = "pending";
this.value = undefined;
this.reason = undefined;
// 保存成功回调
this.onResolvedCallbacks = [];
// 保存失败回调
this.onRejectedCallbacks = [];
let _this = this;
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
function resolve(value) {
if (_this.state === "pending") {
_this.state = "resolved";
_this.value = value;
_this.onResolvedCallbacks.forEach((cb) => cb(value));
}
}
function reject(reason) {
if (_this.state === "pending") {
_this.state = "rejected";
_this.reason = reason;
_this.onRejectedCallbacks.forEach((cb) => cb(reason));
}
}
}
Promise.prototype.then = function (onFulfilled, onRejected) {
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (value) => value;
onRejected =
typeof onRejected === "function"
? onRejected
: (err) => {
throw err;
};
let promise2 = new Promise((resolve, reject) => {
// 等待态判断,此时异步代码还未走完,回调入数组队列
if (this.state === "pending") {
this.onResolvedCallbacks.push(() => {
queueMicrotask(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
this.onRejectedCallbacks.push(() => {
queueMicrotask(() => {
try {
let x = onRejected(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
if (this.state === "resolved") {
queueMicrotask(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
if (this.state === "rejected") {
queueMicrotask(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
});
return promise2;
};
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
reject(new TypeError("请避免Promise循环引用"));
}
let called;
if (x !== null && (typeof x === "object" || typeof x === "function")) {
// 可能是个对象或是函数
try {
let then = x.then;
if (typeof then === "function") {
then.call(
x,
(y) => {
if (called) return;
called = true;
// 递归调用,传入y若是Promise对象,继续循环
resolvePromise(promise2, y, resolve, reject);
},
(r) => {
if (called) return;
called = true;
reject(r);
}
);
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
// 普通值结束递归
resolve(x);
}
} |
class MyPromise {
static PENDING = "pending";
static FULFILLED = "fulfilled";
static REJECTED = "rejected";
constructor(executor) {
this.status = MyPromise.PENDING;
this.value = null;
this.callbacks = [];
executor(this.resolve.bind(this), this.reject.bind(this));
}
resolve(value) {
this.status = MyPromise.FULFILLED;
this.value = value;
setTimeout(() => {
this.callbacks.forEach((cb) => {
cb.onFulfilled(this.value);
});
});
}
reject(value) {
this.status = MyPromise.REJECTED;
this.value = value;
setTimeout(() => {
this.callbacks.forEach((cb) => {
cb.onRejected(this.value);
});
});
}
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== "function") onFulfilled = (value) => value;
if (typeof onRejected !== "function") onRejected = (value) => value;
return new MyPromise((resolve, reject) => {
if (this.status === MyPromise.PENDING) {
this.callbacks.push({
onFulfilled: (value) => {
const res = onFulfilled(value);
this.resolvePromise(res, resolve, reject);
},
onRejected: (value) => {
const res = onFulfilled(value);
this.resolvePromise(res, resolve, reject);
},
});
}
if (this.status === MyPromise.FULFILLED) {
setTimeout(() => {
const res = onFulfilled(this.value);
this.resolvePromise(res, resolve, reject);
});
}
if (this.status === MyPromise.REJECTED) {
setTimeout(() => {
const res = onFulfilled(this.value);
this.resolvePromise(res, resolve, reject);
});
}
});
}
resolvePromise(res, resolve, reject) {
try {
// const res = onFulfilled(value);
if (res instanceof MyPromise) {
res.then(resolve, reject);
} else {
resolve(res);
}
} catch (error) {
reject(error);
}
}
} |
TypeScript 实现,包含 Promise/A+ 测试,可作参考: |
可以用原型链来判断是否为 promise 对象 function isPromise(obj) {
return obj.__proto__ === Promise.prototype;
} |
//将方法放入微队列中执行
function nextTick(fn) {
if (typeof queueMicrotask === "function") {
nextTick = (fn) => {
queueMicrotask(fn);
};
nextTick(fn);
} else if (typeof MutationObserver === "function") {
nextTick = (fn) => {
const observer = new MutationObserver(fn);
const textNode = document.createTextNode("");
observer.observe(textNode, {
attributes: true,
});
textNode.data = 1;
};
nextTick(fn);
} else {
nextTick = (fn) => {
setTimeout(fn, 0);
};
nextTick(fn);
}
}
class MyPromise {
#statusEnum = {
pending: "pending",
fulfilled: "fulfilled",
rejected: "rejected",
};
#status = this.#statusEnum.pending;
#onFulfilledTasks = [];
#onRejectedTasks = [];
#resolve(value) {
if (this.#status === this.#statusEnum.pending) {
this.#status = this.#statusEnum.fulfilled;
this.#onFulfilledTasks.forEach((task) => {
nextTick(() => {
try {
task.onFulfilled(value);
task.resolve(value);
} catch (error) {
task.reject(error);
}
});
});
this.#clear();
}
}
#reject(reason) {
if (this.#status === this.#statusEnum.pending) {
this.#status = this.#statusEnum.rejected;
this.#onRejectedTasks.forEach((task) => {
nextTick(() => {
try {
task.onRejected(reason);
task.resolve(reason);
} catch (error) {
task.reject(error);
}
});
});
this.#clear();
}
}
#clear() {
this.#onFulfilledTasks = [];
this.#onRejectedTasks = [];
}
constructor(executor) {
if (typeof executor !== "function") {
throw new Error("executor must be a function");
}
executor(this.#resolve.bind(this), this.#reject.bind(this));
}
then(onFulfilled, onRejected) {
let resolve, reject;
let thenable = new MyPromise((res, rej) => {
resolve = res;
reject = rej;
});
let isEmptyFn = true;
if (typeof onFulfilled === "function") {
isEmptyFn = false;
this.#onFulfilledTasks.push({ onFulfilled, resolve, reject });
}
if (typeof onRejected === "function") {
isEmptyFn = false;
this.#onRejectedTasks.push({ onRejected, resolve, reject });
}
if (isEmptyFn) {
return this.then(
(value) => value,
(reason) => reason
);
}
//返回一个新的promise,暂时不处理
return thenable;
}
}
//测试用例
let p = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve("success");
}, 1000);
});
p.then((value) => {
console.log(1, value);
});
p.then((value) => {
console.log(2, value);
});
p.then()
.then()
.then((value) => {
console.log(3, value);
});
console.log(p); |
The text was updated successfully, but these errors were encountered: