javascript实现Promise
#source-code #javascript
jerrywu001
创建时间:2023-09-05 05:55:44
Promise使用:使用 Promise - JavaScript | MDN
一个 Promise
必然处于以下几种状态之一:
- 待定(pending): 初始状态,既没有被兑现,也没有被拒绝。
- 已兑现(fulfilled): 意味着操作成功完成。
- 已拒绝(rejected): 意味着操作失败。
定义状态
class MyPromise {
constructor(handle) {
this['[[PromiseStatus]]'] = 'pending';
this['[[PromiseValue]]'] = undefined;
handle(this.resolve.bind(this), this.reject.bind(this));
}
resolve(val) {
if (this['[[PromiseStatus]]'] === 'pending') {
this['[[PromiseStatus]]'] = 'resolved';
this['[[PromiseValue]]'] = val;
}
}
reject(err) {
if (this['[[PromiseStatus]]'] === 'pending') {
this['[[PromiseStatus]]'] = 'rejected';
this['[[PromiseValue]]'] = err;
}
}
}
then方法
then() 方法返回一个 Promise。它最多需要有两个参数:Promise 的成功和失败情况的回调函数。
需要异步执行resolveFn和rejectFn,不然MyPromise里执行resolve或reject时,then里面的方法还没读取到。
可以用MutationObserver模拟微任务。
class MyPromise {
constructor(handle) {
this['[[PromiseStatus]]'] = 'pending';
this['[[PromiseValue]]'] = undefined;
handle(this.resolve.bind(this), this.reject.bind(this));
}
resolve(val) {
if (this['[[PromiseStatus]]'] === 'pending') {
this['[[PromiseStatus]]'] = 'resolved';
this['[[PromiseValue]]'] = val;
const run = () => {
this.resolveFn(val);
};
const observer = new MutationObserver(run);
observer.observe(document.body, {
attributes: true,
});
document.body.setAttribute('key', 'any value');
}
}
reject(err) {
if (this['[[PromiseStatus]]'] === 'pending') {
this['[[PromiseStatus]]'] = 'rejected';
this['[[PromiseValue]]'] = err;
const run = () => {
this.rejectFn(err);
};
const observer = new MutationObserver(run);
observer.observe(document.body, {
attributes: true,
});
document.body.setAttribute('key', 'any value');
}
}
then(resolveFn, rejectFn) {
this.resolveFn = resolveFn;
this.rejectFn = rejectFn;
}
}
并列多个then
并列的then都是获取到调用then的Promise对象的值。
const p = new Promise((resolve, reject) => {
resolve('success');
// reject("err");
});
p.then((res) => {
console.log(1, res);
});
p.then((res) => {
console.log(2, res);
});
// 1 "success"
// 2 "success"
遍历then回调
需要用一个数组存储then传进来的函数。在resolved或rejected后遍历执行。
class MyPromise {
constructor(handle) {
this['[[PromiseStatus]]'] = 'pending';
this['[[PromiseValue]]'] = undefined;
this.resolveQueue = [];
this.rejectQueue = [];
handle(this.resolve.bind(this), this.reject.bind(this));
}
resolve(val) {
if (this['[[PromiseStatus]]'] === 'pending') {
this['[[PromiseStatus]]'] = 'resolved';
this['[[PromiseValue]]'] = val;
const run = () => {
let cb;
// 直接删除而不是forEach遍历执行,是因为都是用的事件监听,不然后面会被重复执行
while ((cb = this.resolveQueue.shift())) {
cb && cb(val);
}
};
const observer = new MutationObserver(run);
observer.observe(document.body, {
attributes: true,
});
document.body.setAttribute('key', 'any value');
}
}
reject(err) {
if (this['[[PromiseStatus]]'] === 'pending') {
this['[[PromiseStatus]]'] = 'rejected';
this['[[PromiseValue]]'] = err;
const run = () => {
let cb;
while ((cb = this.rejectQueue.shift())) {
cb && cb(err);
}
};
const observer = new MutationObserver(run);
observer.observe(document.body, {
attributes: true,
});
document.body.setAttribute('key', 'any value');
}
}
then(resolveFn, rejectFn) {
this.resolveQueue.push(resolveFn);
this.rejectQueue.push(rejectFn);
}
}
链式调用then
then执行返回的是一个新的promise对象,
可以返回正常值,若返回promise对象,会自动解析入参传递给下一个then。
const p2 = new Promise((resolve, reject) => {
resolve('success');
// reject("err");
})
.then((res) => {
console.log(1, res); // 1 "success"
return 1;
})
.then((res) => {
console.log(2, res); // 2 1
return new Promise((resolve) => {
resolve('2promise');
});
})
.then((res) => {
console.log(3, res); // 3 "2promise"
});
class MyPromise {
constructor(handle) {
this['[[PromiseStatus]]'] = 'pending';
this['[[PromiseValue]]'] = undefined;
this.resolveQueue = [];
this.rejectQueue = [];
handle(this.resolve.bind(this), this.reject.bind(this));
}
resolve(val) {
if (this['[[PromiseStatus]]'] === 'pending') {
this['[[PromiseStatus]]'] = 'resolved';
this['[[PromiseValue]]'] = val;
const run = () => {
let cb;
while ((cb = this.resolveQueue.shift())) {
cb && cb(val);
}
};
const observer = new MutationObserver(run);
observer.observe(document.body, {
attributes: true,
});
document.body.setAttribute('key', 'any value');
}
}
reject(err) {
if (this['[[PromiseStatus]]'] === 'pending') {
this['[[PromiseStatus]]'] = 'rejected';
this['[[PromiseValue]]'] = err;
const run = () => {
let cb;
while ((cb = this.rejectQueue.shift())) {
cb && cb(err);
}
};
const observer = new MutationObserver(run);
observer.observe(document.body, {
attributes: true,
});
document.body.setAttribute('key', 'any value');
}
}
then(resolveFn, rejectFn) {
return new MyPromise((resolve, reject) => {
// 返回一个新的Promise
// 需要取到上一个then的返回值
// 判断返回的结果是正常值直接返回,是Promise值需要取出来返回
function TResolveFn(val) {
const result = resolveFn && resolveFn(val);
if (result instanceof MyPromise) {
result.then(
(res) => {
resolve(res);
},
(err) => {
reject(err);
}
);
} else {
resolve(result);
}
}
this.resolveQueue.push(TResolveFn);
function TRejectFn(val) {
const result = rejectFn && rejectFn(val);
if (result instanceof MyPromise) {
result.then(
(res) => {
resolve(res);
},
(err) => {
reject(err);
}
);
} else {
reject(result);
}
}
this.rejectQueue.push(TRejectFn);
});
}
}
catch和finally方法
catch(fn) {
return this.then(undefined, fn);
}
finally(fn) {
//不管成功失败都会执行
this.then(fn, fn);
}
相关静态方法
resolve
返回一个成功状态Promise
static resolve(result) {
return new MyPromise((resolve) => {
resolve(result);
});
}
reject
返回一个失败状态Promise
static reject(result) {
return new MyPromise((resolve, reject) => {
reject(result);
});
}
all
接受一个Promise数组,返回一个新的Promise, 如果Promise都成功,按数组顺序返回成功状态, 若有一个失败,返回最先被reject的值。
static all(promiseAry) {
const result = [];
let num = 0;
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promiseAry.length; i++) {
promiseAry[i].then(
(res) => {
result[i] = res;
num++;
if (num === promiseAry.length) {
resolve(result);
}
},
(err) => {
reject(err);
}
);
}
});
}
race
接受一个Promise数组,返回一个新的Promise, 返回最快响应的Promise
static race(promiseAry) {
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promiseAry.length; i++) {
promiseAry[i].then(
(res) => {
resolve(res);
},
(err) => {
reject(err);
}
);
}
});
}
allSettled
接受一个Promise数组,返回一个新的Promise,
不管成功和失败都会返回,数据结构如下
// 成功:
// {
// status: "fulfilled"
// value: "success"
// }
// 失败
// {
// reason: "err"
// status: "rejected"
// }
static allSettled(promiseAry) {
const result = [];
let num = 0;
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promiseAry.length; i++) {
promiseAry[i].then(
(res) => {
result[i] = {
status: 'fulfilled',
value: res,
};
num++;
if (num === promiseAry.length) {
resolve(result);
}
},
(err) => {
result[i] = {
status: 'rejected',
value: err,
};
num++;
if (num === promiseAry.length) {
resolve(result);
}
}
);
}
});
}
最终代码
class MyPromise {
constructor(handle) {
this['[[PromiseStatus]]'] = 'pending';
this['[[PromiseValue]]'] = undefined;
this.resolveQueue = [];
this.rejectQueue = [];
handle(this.resolve.bind(this), this.reject.bind(this));
}
resolve(val) {
if (this['[[PromiseStatus]]'] === 'pending') {
this['[[PromiseStatus]]'] = 'resolved';
this['[[PromiseValue]]'] = val;
const run = () => {
let cb;
// 直接删除而不是forEach遍历执行,是因为都是用的事件监听,不然后面会被重复执行
while ((cb = this.resolveQueue.shift())) {
cb && cb(val);
}
};
const observer = new MutationObserver(run);
observer.observe(document.body, {
attributes: true,
});
document.body.setAttribute('key', 'any value');
}
}
reject(err) {
if (this['[[PromiseStatus]]'] === 'pending') {
this['[[PromiseStatus]]'] = 'rejected';
this['[[PromiseValue]]'] = err;
const run = () => {
let cb;
while ((cb = this.rejectQueue.shift())) {
cb && cb(err);
}
};
const observer = new MutationObserver(run);
observer.observe(document.body, {
attributes: true,
});
document.body.setAttribute('key', 'any value');
}
}
then(resolveFn, rejectFn) {
this.resolveQueue.push(resolveFn);
this.rejectQueue.push(rejectFn);
}
static allSettled(promiseAry) {
const result = [];
let num = 0;
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promiseAry.length; i++) {
promiseAry[i].then(
(res) => {
result[i] = {
status: 'fulfilled',
value: res,
};
num++;
if (num === promiseAry.length) {
resolve(result);
}
},
(err) => {
result[i] = {
status: 'rejected',
value: err,
};
num++;
if (num === promiseAry.length) {
resolve(result);
}
}
);
}
});
}
static race(promiseAry) {
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promiseAry.length; i++) {
promiseAry[i].then(
(res) => {
resolve(res);
},
(err) => {
reject(err);
}
);
}
});
}
static all(promiseAry) {
const result = [];
let num = 0;
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promiseAry.length; i++) {
promiseAry[i].then(
(res) => {
result[i] = res;
num++;
if (num === promiseAry.length) {
resolve(result);
}
},
(err) => {
reject(err);
}
);
}
});
}
static reject(result) {
return new MyPromise((resolve, reject) => {
reject(result);
});
}
static resolve(result) {
return new MyPromise((resolve) => {
resolve(result);
});
}
catch(fn) {
return this.then(undefined, fn);
}
finally(fn) {
// 不管成功失败都会执行
this.then(fn, fn);
}
}