根据Promise A+规范来实现一个简易的Promise
首先 new Promise()得到的是一个对象
class Promise{
}
module.exports = Promise
Promise对象的输入是函数
关于输入有三个要求:
-
检查类型:Promise的输入必须是一个函数,否则报错
-
立刻执行传下来的函数
-
函数有两个参数,分别是resolve和reject
class Promise2 {
resolve(result) {
}
reject(reason) {
}
constructor(fn) {
if (typeof fn !== 'function') {
throw new Error('Promise必须接受一个函数');
}
//传进来的函数就会被立刻调用,第一个参数是this.resolve, 第二个参数是this.reject
fn.call(this, this.resolve.bind(this), this.reject.bind(this));
}
Promise对象的输出是带有then方法的对象
所以我们继续完善then方法
then方法有以下要求:
- 接受两个参数, success 和 fail
- 如果两个参数没有传,或者类型不是函数,不报错,但是也不会执行什么操作
- 同一个promise可以多次调用then
promise1.then
promise1.then - then 的两个参数 是让 resolve和reject去调用的
为了处理可能多次调用then的情况,我们用一个数组callbacks储存多次then传进来的参数,用一个数组handle存储每次then的传进来的参数
then(succeed?, fail?) {
let handle = [];
if (typeof succeed === 'function') {
handle[0] = succeed;
}
if (typeof fail === 'function') {
handle[1] = fail;
}
this.callbacks.push(handle);
}
用Resolve调用then的第一个参数
resolve函数需要做两件事:
- 修改Promise的状态,并且保证resolve函数只能执行一次
- 调用then的第一个参数
resolve(result) {
// 保证resolve只能被调用一次,如果状态不是‘pending’就直接退出
if (this.state !== 'pending') {
return;
}
this.state = 'fulfilled';
setTimeout(() => {
this.callbacks.forEach(handle => {
if (typeof handle[0] === 'function') {
handle[0].call(undefined, result);
}
});
});
}
用Reject调用then的第二个参数
reject函数也需要做两件事:
- 修改Promise的状态,并且保证reject函数只能执行一次
- 调用then的第二参数
reject(reason) {
// 保证reject只能被调用一次
if (this.state !== 'pending') return;
this.state = 'rejected';
setTimeout(() => {
this.callbacks.forEach(handle => {
if (typeof handle[1] === 'function') {
handle[1].call(undefined, reason);
}
});
});
}
最终完成的Promise就是:
class Promise2 {
state = 'pending';
callbacks = [];
resolve(result) {
// 保证resolve只能被调用一次
if (this.state !== 'pending') {
return;
}
this.state = 'fulfilled';
// 异步调用then的第一个参数
setTimeout(() => {
this.callbacks.forEach(handle => {
if (typeof handle[0] === 'function') {
handle[0].call(undefined, result);
}
});
});
}
reject(reason) {
// 保证reject只能被调用一次
if (this.state !== 'pending') return;
this.state = 'rejected';
// 异步调用then的第二个参数
setTimeout(() => {
this.callbacks.forEach(handle => {
if (typeof handle[1] === 'function') {
handle[1].call(undefined, reason);
}
});
});
}
constructor(fn) {
if (typeof fn !== 'function') {
throw new Error('Promise必须接受一个函数');
}
//传进来的函数就会被立刻调用
fn.call(this, this.resolve.bind(this), this.reject.bind(this));
}
then(succeed?, fail?) {
let handle = [];
if (typeof succeed === 'function') {
handle[0] = succeed;
}
if (typeof fail === 'function') {
handle[1] = fail;
}
this.callbacks.push(handle);
}
}
export default Promise2;
实现Promise.all
思路:
首先分析输入输出
输入:数组,可能有字符串,数字,Promise对象
输出:一个Promise对象
然后分析promise.all的特性:
数组里的全部元素成功,才算成功
有一个失败,立刻reject
所以遍历数组时,用一个空数组results记录每次的结果,如果results的数组长度 和 输入的数组长度一致,就表示都成功,就resolve这个数组
反之,遍历时如果有一个失败就reject
all(promises){
// 返回一个Promise对象
return new Promise((resolve, reject)=>{
// 考虑极端情况,如果是空数组直接返回
if(promises.length === 0) {
resolve([])
}else {
let results = []
for (let i = 0; i < promises.length; i++) {
promises[i] = promises[i] instanceof Promise? promises[i]: Promise.resolve(promises[i])
// 用then 去拿结果
promises[i].then((result)=>{
results.push(result)
// 只有等到都成功了才一起resolve
if(result.length === promises.length){
resolve(results)
}
},(err)=>{
reject(err)
})
}
}
})
}
实现Promise.race
/**
* Promise.race
* @description 只要有一个promise对象进入FULFILLED 或者 REJECTED 状态的话,就会继续执行后面的处理
* @param {*} values 接受promise对象组成的数组作为参数
* @returns 返回一个Promise实例
*/
static race(values) {
return new Promise((resolve, reject) => {
values.forEach((promise) => {
promise.then(resolve, reject)
})
})
}
实现Promise.reject和Promise.resolve
// 默认产生一个成功的promise
static resolve(value) {
return new Promise((resolve, reject) => {
resolve(value)
})
}
// 默认产生一个失败的promise
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
参考: