在上篇中,我们已经实现了Promise的基本功能及then,catch两个实例方法。下面我们来实现ES6中的Promise对象的所有实例方法与静态方法。
源码地址,欢迎star🤭
-
Promise.prototype.finally()
该方法不论 Promise 对象最后状态如何,都会执行传入的回调。
关于该方法的实现有两点要说明
1.finally方法的回调不接收任何参数,这表明该回调的执行不依赖Promise的状态和结果。
2.finally不会阻止结果的传递。即如果finally方法之后还有链式调用的then或catch方法,则会继续调用。因此finally方法应该返回一个Promise,其结果和状态就是调用finally方法的Promise的状态和结果。这里很自然的可以想到使用then方法,因为then方法特性恰好符合前面所述,因此finally方法实质上是then方法的特例。
Promise.prototype.finally = function (onFinished) {
return this.then((val) => {
onFinished();
return val;
},(reason) => {
onFinished();
throw reason
});
};
-
Promise.resolve()
该方法返回一个promise对象,结果和状态由入参决定。
Promise.resolve = function (value) {
//返回promise对象
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(
(res) => {
resolve(res);
},
(reason) => {
reject(reason);
}
);
} else {
//状态设置为成功
resolve(value);
}
});
};
-
Promise.reject()
该方法返回一个状态为 rejected的Promise 实例,无论入参是什么,返回的实例的状态总是rejected。
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
};
-
Promise.all()
该方法接受一个由Promise实例组成的数组作为参数,返回一个Promise。该Promise状态有两种情况,我们将Promise实例组成的数组暂且称为arr,all返回的Promise称为p。
1.只有arr所有成员的状态都变成fulfilled,p的状态才会变成fulfilled,且其结果为arr所有成员的结果。
2.只要arr中有一个成员的状态变为reject,则p的状态立即变为rejected,且其结果就是那个状态变为reject的成员的结果。
// 判断是否是promise
let isPromise = (x) => {
if ((typeof x === "object" && x != null) || typeof x === "function") {
if (typeof x.then === "function") {
return true;
}
}
return false;
};
Promise.all = function (promises) {
//返回结果为promise对象
return new Promise((resolve, reject) => {
// 声明计数变量
let count = 0;
// 结果数组
let arr = [];
//遍历
for (let i = 0; i < promises.length; i++) {
if (isPromise(promises[i])) {
promises[i].then(
(res) => {
//得知对象的状态是成功,则将当前promise对象成功的结果 存入到数组中
count++
// 这里不能用push ,因为我们要保证结果数组的顺序和传入的
// promise数组的顺序一致。
// 如果用push,则不能保证顺序,因为异步操作返回结果的快慢有所不同。
arr[i] = res;
// 只有全部promise均成功 all才成功
if (count === promises.length) {
//修改状态
resolve(arr);
}
},
(reason) => {
// 对象的状态是失败,直接reject
reject(reason);
}
);
} else {
// 非promise 直接推入结果数组
count++;
arr[i] = promises[i];
if (count === promises.length) {
resolve(arr);
}
}
}
});
};
-
Promise.race()
方法接受一个由Promise实例组成的数组作为参数(arr),返回一个Promise(p)。该Promise状态和结果取决去arr中率先改变状态的成员,即p的状态和结果是率先改变状态的成员的状态和结果。
如果arr的某个成员不是 Promise 实例,会将其先转为 Promise 实例,再进一步处理。
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
// 非Promise先转化为Promise
if (!(promises[i] instanceof Promise)) {
promises[i] = Promise.resolve(promises[i]);
}
promises[i].then(
(v) => {
//谁率先改变状态 返回值就是谁的结果
resolve(v);
},
(r) => {
//修改返回对象的状态为 『失败』
reject(r);
}
);
}
});
};
-
Promise.any()
该方法接受一个由Promise实例组成的数组作为参数(arr),返回一个Promise(p)。该方法的行为恰好与Promsie.all方法相反。只要arr有一个成员变成fulfilled状态,p就会变成fulfilled状态;当所有成员都变成rejected状态,p就会变成rejected状态。
Promise.any = function (promises) {
return new Promise((resolve, reject) => {
let count = 0;
for (let i = 0; i < promises.length; i++) {
if (!(promises[i] instanceof Promise)) {
promises[i] = Promise.resolve(promises[i]);
}
promises[i].then(
(res) => {
resolve(res);
},
() => {
count++;
if (count === promises.length) {
//该方法抛出的错误是一个 AggregateError 实例。
//它相当于一个数组,每个成员对应一个被rejected的操作所抛出的错误。
reject(new AggregateError([], "All promises were rejected"));
}
}
);
}
});
};
-
Promise.allSettled()
该方法接受一组 Promise 实例作为参数(arr),包装成一个新的 Promise 实例(p)。只有arr所有成员都返回结果,不管是fulfilled还是rejected,p才会结束。该方法返回的新的 Promise 实例,一旦结束,状态总是fulfilled,不会变成rejected。
Promise.allSettled = function (promises) {
return new Promise(async (resolve) => {
let result = [];
for (let i = 0; i < promises.length; i++) {
if (promises[i] instanceof Promise) {
try {
const res = await promises[i]
result[i] = {
status: 'Fulfilled',
value: res,
};
} catch (reason) {
result[i] = {
status: 'Rejected',
reason,
};
}
} else {
result[i] = {
status: 'Fulfilled',
value: promises[i],
};
}
}
resolve(result);
});
};
至此,我们已经完成了A+规范的Promise及ES6中所有的实例方法与静态方法的实现。如果觉得对你有帮助,欢迎三连支持😀。
参考:https://es6.ruanyifeng.com/#docs/promise