Promise 相关手写
javascript promise 手写实现
Promise 手写代码
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MPromise {
FULFILLED_CALLBACK_LIST = [];
REJECTED_CALLBACK_LIST = [];
constructor(fn) {
this.status = PENDING;
this.result = null;
this.reason = null;
try {
fn(this.resolve.bind(this), this.reject.bind(this));
} catch (e) {
this.reject(e);
}
}
resolve(value) {
if (this.status === PENDING) {
this.status = FULFILLED;
this.result = value;
this.FULFILLED_CALLBACK_LIST.forEach((cb) => {
cb(this.result);
});
}
}
reject(value) {
this.status = REJECTED;
this.reason = value;
this.REJECTED_CALLBACK_LIST.forEach((cb) => {
cb(this.reason);
});
}
then(onFulFilled, onRejected) {
switch (this.status) {
case FULFILLED: {
const newPromise = new MPromise((resolve, reject) => {
queueMicrotask(() => {
try {
if (typeof onFulFilled !== "function") {
resolve(this.result);
} else {
let x = onFulFilled(this.result);
resolvePromise(newPromise, x, resolve, reject);
}
} catch (e) {
reject(e);
}
});
});
return newPromise;
}
case REJECTED: {
const newPromise = new MPromise((resolve, reject) => {
queueMicrotask(() => {
try {
if (typeof onRejected !== "function") {
reject(this.reason);
} else {
let x = onRejected(this.reason);
resolvePromise(newPromise, x, resolve, reject);
}
} catch (e) {
reject(e);
}
});
});
return newPromise;
}
case PENDING: {
// 一个Promise可以多次.then,当它状态还是pending的时候,需要把回调维护到数组里,等到状态改变时同时调用
const newPromise = new MPromise((resolve, reject) => {
this.FULFILLED_CALLBACK_LIST.push(() =>
queueMicrotask(() => {
try {
if (typeof onFulFilled !== "function") {
resolve(this.result);
} else {
let x = onFulFilled(this.result);
resolvePromise(newPromise, x, resolve, reject);
}
} catch (e) {
reject(e);
}
})
);
this.REJECTED_CALLBACK_LIST.push(() =>
queueMicrotask(() => {
try {
if (typeof onRejected !== "function") {
reject(this.reason);
} else {
let x = onRejected(this.reason);
resolvePromise(newPromise, x, resolve, reject);
}
} catch (e) {
reject(e);
}
})
);
});
return newPromise;
}
}
}
// catch和finally方法不需要 也符合PromiseA+规范,这边写上是为了方便看这两个方法的手写实现
catch(onRejected) {
return this.then(undefined, onRejected);
}
finally(cb) {
return this.then(cb, cb);
}
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
throw new TypeError("循环引用");
} else if (x instanceof MPromise) {
x.then((y) => {
resolvePromise(promise2, y, resolve, reject);
}, reject);
} else if ((typeof x === "object" && x !== null) || typeof x === "function") {
let then = null;
try {
then = x.then;
} catch (e) {
return reject(e);
}
if (typeof then === "function") {
// 如果then方法中 resolvePromise 和 rejectPromise 被同时调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用
let called = false;
try {
then.call(
x,
(y) => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
},
(e) => {
if (called) return;
called = true;
reject(e);
}
);
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
} else {
resolve(x);
}
}
PromiseA+规范 测试
MPromise.deferred = function () {
let result = {};
result.promise = new MPromise((resolve, reject) => {
result.resolve = resolve;
result.reject = reject;
});
return result;
};
module.exports = MPromise;
npm i promises-aplus-tests -D
npx promises-aplus-tests MPromise.js
Promise 静态方法实现
Promise.resolve
const myPromiseResolve = (value) => {
if (value instanceof Promise) {
return value;
} else if (
value instanceof Object &&
Reflect.ownKeys(value).includes("then") &&
typeof value.then === "function"
) {
return new Promise((resolve, reject) => {
value.then(resolve, reject);
});
}
return new Promise((r) => {
r(value);
});
};
测试
myPromiseResolve(new Promise((r) => r(1))).then(console.log); // 1
myPromiseResolve({
then: (onFulFilled) => {
onFulFilled(1);
},
}).then(console.log); // 1
myPromiseResolve(1).then(console.log); // 1
Promise.reject
const myPromiseReject = (value) => {
return new Promise((resolve, reject) => {
reject(value);
});
};
测试
myPromiseReject(1).then(null, console.log); // 1
Promise.prototype.catch & Promise.prototype.finally
catch(onRejected) {
return this.then(undefined, onRejected);
}
finally(cb) {
return this.then(cb, cb);
}
Promise.all
const myPromiseAll = (promises) => {
return new Promise((resolve, reject) => {
if (Array.isArray(promises)) {
let result = [];
let count = 0;
if (promises.length === 0) {
return resolve(promises);
}
promises.forEach((item, index) => {
if (item instanceof Promise) {
item.then(
(res) => {
count++;
result[index] = res;
if (count === promises.length) resolve(result);
},
(reason) => {
reject(reason);
}
);
} else {
count++;
result[index] = item;
if (count === promises.length) resolve(result);
}
});
} else {
reject(new TypeError("非数组"));
}
});
};
测试
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, "foo");
});
myPromiseAll([promise1, promise2, promise3]).then((values) => {
console.log(values); // [3, 42, 'foo']
});
Promise.allSettled
const myPromiseAllSettled = (promises) => {
return new Promise((resolve, reject) => {
if (Array.isArray(promises)) {
let result = [];
let count = 0;
if (promises.length === 0) {
return resolve(promises);
}
promises.forEach((item, index) => {
// 非promise值,通过Promise.resolve转换为promise进行统一处理
Promise.resolve(item).then(
(res) => {
count++;
result[index] = {
status: "fulfilled",
value: res,
};
if (count === promises.length) resolve(result);
},
(reason) => {
count++;
result[index] = {
status: "rejected",
reason: reason,
};
if (count === promises.length) resolve(result);
}
);
});
} else {
reject(new TypeError("非数组"));
}
});
};
测试
const p1 = Promise.resolve(3);
const p2 = new Promise((resolve, reject) => setTimeout(reject, 100, "foo"));
const p3 = 1;
const ps = [p1, p2, p3];
myPromiseAllSettled(ps).then((results) =>
results.forEach((result) => console.log(result))
);
/*
{ status: 'fulfilled', value: 3 }
{ status: 'rejected', reason: 'foo' }
{ status: 'fulfilled', value: 1 }
*/
Promise.any
// Promise.any() 接收一个Promise可迭代对象,只要其中的一个 promise 成功,就返回那个已经成功的 promise 。
// 如果可迭代对象中没有一个 promise 成功(即所有的 promises 都失败/拒绝),
// 就返回一个失败的 promise 和AggregateError类型的实例,它是 Error 的一个子类,用于把单一的错误集合在一起。
const myPromiseAny = (promises) => {
return new Promise((resolve, reject) => {
if (Array.isArray(promises)) {
let count = 0;
let errors = [];
if (promises.length === 0) {
return reject(new Error("All promises were rejected"));
}
promises.forEach((item, index) => {
Promise.resolve(item).then(
(res) => {
resolve(res);
},
(reason) => {
count++;
errors.push(reason);
if (count === promises.length) reject(new Error(errors));
}
);
});
} else {
reject(new TypeError("非数组"));
}
});
};
测试
const pErr = new Promise((resolve, reject) => {
reject("总是失败");
});
const pSlow = new Promise((resolve, reject) => {
setTimeout(resolve, 500, "最终完成");
});
const pFast = new Promise((resolve, reject) => {
setTimeout(resolve, 100, "很快完成");
});
myPromiseAny([pErr, pSlow, pFast]).then((value) => {
console.log(value); // 很快完成
});
const pErr1 = new Promise((resolve, reject) => {
reject("总是失败");
});
const pErr2 = new Promise((resolve, reject) => {
reject("总是失败");
});
const pErr3 = new Promise((resolve, reject) => {
reject("总是失败");
});
myPromiseAny([pErr1, pErr2, pErr3]).catch((e) => {
console.log(e); // [总是失败,总是失败,总是失败]
});
Promise.race
// Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。
const myPromiseRace = (promises) => {
return new Promise((resolve, reject) => {
if (Array.isArray(promises)) {
// 如果传入的迭代promises是空的,则返回的 promise 将永远等待。
if (promises.length > 0) {
promises.forEach((item) => {
Promise.resolve(item).then(resolve, reject);
});
}
} else {
reject(new TypeError("非数组"));
}
});
};
测试
const p4 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, "one");
});
const p5 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, "two");
});
myPromiseRace([p4, p5]).then((value) => {
console.log("p5 :>> ", value); // two
});
除了 catch 和 finally, 以上方法都属于 Promise 类上的静态方法,可以用 static 关键字挂在 MPromise 上 catch 和 finally 在 MPromise 类中实现了
参考链接
https://juejin.cn/post/7043758954496655397 https://juejin.cn/post/7044088065874198536