0%

手写Promise

根据 Promise A+ 规范进行实现,并额外实现其 allrace 等静态方法。

代码的实现完美符合 Promise A+ 规范

Promise / A+ 规范

所谓规范,也就是我们实现promise时,需要遵循的一些规范(当然你也可以不遵循……)。

那么,规范这种东西我懒得写了,promise A+ 具体规范可以看下面:

我们的主要任务还是以代码实现为主!

基本结构

通过原生Promise我们可以知道,Promise 它实际上就是一个构造函数,毕竟只有构造函数才可以使用 new ,那么,我们就以ES6语法来进行我们的代码实现。

首先,把我们Promise这个类的骨架给搭建起来

class Promise {
constructor() {

}
}

执行器

Promise接收一个参数,这个参数是一个函数,同时它包含2个形参 resolvereject

那么,我们就需要在构造器中接收这个函数。

只要你基础不是很差,应该能看出,resolvereject 是由我们的类进行传递的,也就是说,这2个方法是Promise自己身上的方法

class Promise {
constructor(executor) {
executor(this.resolve, this.reject);
}

resolve = () => {}

reject = () => {}
}

在这里,我们做了几件事:

  1. 接收executor这个执行函数
  2. 往类中添加resolve和reject两个方法
  3. 执行executor并传递我们的resolve和reject给它

实现resolve

用过原生promise的都应该知道,resolve是一个函数,且该函数可以接收一个参数,下面是原生Promise的例子

// 原生Promise
new Promise((resolve, reject) => {
resolve(1); // 这个就是我们要实现的
}).then(value => {
console.log(value); // 只有resolve了,才能进入then这里,而value就是上面resolve的1
});

先不管then,我们先来实现resolve,在实现之前,根据A+规范,我们知道:

promise有三种状态 pendingfulfilledrejected,分别代表等待中,成功,失败。

而在promise中一旦resolve,就会把promise的状态从pending变为 fulfilled

并且,你 resolve(1) 中的参数 1 我也得接收的对吧?我们就用一个变量 value 来接收。resolve的参数是可选的,你可以传,你传了我就接收,你不传我就默认undefined。

最后,我们要知道,resolve的作用是把promise从pending 状态转为 fulfilled 状态。

const PENDING = 'pending'; // pending等待状态
const FULFILLED = 'fulfilled'; // resolve成功状态
const REJECTED = 'rejected'; // reject失败状态

class Promise {
state = PENDING; // promise的初始状态,也就是默认状态是pending
value = null; // resolve的value

constructor(executor) {
executor(this.resolve, this.reject);
}

resolve = (value) => {
// 只有状态为pending时才可以resolve
if(this.state === PENDING) {
// 修改状态为fulfilled
this.state = FULFILLED;
this.value = value;
}
}
}

实现reject

reject的实现与上面的resolve差不多,区别在于,它是将promise的状态从 pending 状态转为 rejected状态。

同样的,reject也可以接收一个参数,我们就用一个变量 reason 来保存它的参数。

const PENDING = 'pending'; // pending等待状态
const FULFILLED = 'fulfilled'; // resolve成功状态
const REJECTED = 'rejected'; // reject失败状态

class Promise {
state = PENDING; // promise的初始状态,也就是默认状态是pending
value = null; // resolve的value
reason = null; // reject的reason

constructor(executor) {
executor(this.resolve, this.reject);
}

reject = (reason) => {
// 只有状态为pending时才可以reject
if(this.state === PENDING) {
// 修改状态为fulfilled
this.state = FULFILLED;
this.reason = reason;
}
}
}

测试

写到这里,我们先来进行一个小小的测试,看看我们写的代码是否有误。

new Promise((resolve, reject) => {
console.log('执行我们自己的promise');
})

如果执行上面的代码后能正常输出console的内容,则证明无误。

我们接着往下写。

实现then(重点难点)

在实现之前,我们应该知道几个点:

  1. then什么时候会被触发
  2. then有多少个形参
  3. 假如then有返回值怎么办

我们先来回答上面的三个问题

// 原生Promise
new Promise((resolve, reject) => {
console.log(1);
resolve(2);
}).then(value => {
console.log(value);
return 3;
}, err => {
console.log(err);
}).then(value => {
console.log(value);
})

观察上面的代码,我们知道

  1. 只有在Promise被实例化的同时,执行了resolve,才会触发then
  2. then有2个形参,分别对应成功(fulfilled)和失败(rejected)两种状态的回调函数
  3. then里的返回值会作为下一个then成功状态的回调函数参数

最后,我们还得知道,在 A+ 规范中规定了,then的两个形参名字应为:

  • onFulfilled:promise状态成功时,参数为当前状态值value或者没有。
  • onRejected:promise状态为失败时,参数是失败信息reason或者没有。

基本形态

then方法本质上就是我们Promise类上的一个方法,它接收2个形参,就这样。

class Promise {
/*
......
......
*/

then = (onFulfilled, onReject) => {

}
}

onFulfilled

onFulfilled是干嘛的呢?它是,当我们promise当前的状态为成功时,会调用的函数。

它有一个参数value,就是我们 resolve(value) 中的 value

// then中的onFulfilled实现
then = (onFulfilled, onReject) => {
// 只有当前状态为成功fulfilled时才执行
if(this.state === FULFILLED) {
// 执行onFulfilled并把我们的value传递给它
onFulfilled(this.value);
}
}

onReject

onReject与onFulfilled差不多,区别在于,只有当我们promise的状态为失败时,才会调用。

它有一个参数,就是我们 reject(reason) 中的 reason

// then中的onReject实现
then = (onFulfilled, onReject) => {
// 只有当前状态为成功rejected时才执行
if(this.state === REJECTED) {
// 执行onReject并把我们的reason传递给它
onReject(this.reason);
}
}

测试

那么,我们来测试一波

// 我们的promise
new Promise((resolve, reject) => {
console.log('value', 1);
resolve(2);
}).then(value => {
console.log('value', value);
});

// 执行结果
// value 1
// value 2

观察执行结果,能看出,我们的代码是 完美 实现。

但是,假如我们的promise里涉及到异步操作呢?

// 我们的promise
new Promise((resolve, reject) => {
console.log('value', 1);
// 模拟异步代码,假设我们正在发送ajax请求
setTimeout(() => {
resolve(2);
}, 0);
}).then(value => {
console.log('value', value);
});

// 执行结果
// value 1

why! 为什么?我们的 value 1哪去了?

其实是这样的,我们的 setTimeout 是异步代码,因此会被延迟执行,哪怕你写的时间是 0。

随后,js把你的异步代码给丢到一边玩泥巴后,又往后看了看还有没有别的代码,它发现了 then

由于我们此刻的then是同步代码,所以它就先执行then了,把then的事情干完了,才去执行我们的setTimeout。

你想想,我then都执行完了,你还resolve有毛用?

异步处理

通过上面的解释说明,我们知道了, 由于then先执行的缘故,导致我们的resolve变得没有了意义,那么我们的解决方案是什么呢?

首先,我们知道,promise的初始状态都是pending,且只有 resolvereject 可以修改状态。

那么,我 resolve 都还没有执行,此时promise的状态不就是 pending 了嘛,所以呀,我们只需要 在then里处理pending状态 就可以了。

class Promise {
// ....
onFulfilledCallback = null; // 成功时执行的函数
onRejectedCallback = null; // 失败时执行的函数

// then中的onFulfilled实现
then = (onFulfilled, onReject) => {
// 只有当前状态为成功pending时才执行
if(this.state === PENDING) {
// 保存成功时的处理函数
this.onFulfilledCallback = onFulfilled;
// 保存失败时的处理函数
this.onRejectedCallback = onReject;
}
}
}

上面是在 then 中增加了对pending状态的判断,以及增加了2个类属性。

接下来,我们还得再做一件事,我们上面把成功和失败的处理函数保存起来了,那么应该在什么时候,又在哪调用呢?

答案是:resolvereject

resolve = () => {
resolve = (value) => {
// 只有状态为pending时才可以resolve
if (this.state === PENDING) {
// ....
// 调用resolve修改状态为成功时,执行成功的处理函数
this.onFulfilledCallback && this.onFulfilledCallback(value);
}
}

reject = (reason) => {
// 只有状态为pending时才可以reject
if (this.state === PENDING) {
// ....
// 调用reject修改状态为失败时,执行失败的处理函数
this.onRejectedCallback && this.onRejectedCallback(reason);
}
}
}

测试

再次进行异步代码测试

// 我们的promise
new Promise((resolve, reject) => {
console.log('value', 1);
// 模拟异步代码,假设我们正在发送ajax请求
setTimeout(() => {
resolve(2);
}, 1500);
}).then(value => {
console.log('value', value);
});

// 执行结果
// value 1
// value 2

可以看到,我们定时器设置了1.5秒,在输出 value 1的时候,等待了1.5秒,随后输出 value 2。

那么,我们的异步处理就搞定了。

到这里,我们的代码就已经开始复杂起来了,不过问题不大,假如你们感觉理解起来还有点晕,先不要往下看,先把上面的知识理清楚,多写多思考几遍就会了。

链式调用

我们先来看原生的promise链式调用例子

new Promise((resolve, reject) => {
resolve(1);
}).then().then().then().then().....

可以看到,可以无限制的往下点出then。

而我们的呢,结果竟是……

// 我们的promise
new Promise((resolve, reject) => resolve(1))
.then(value => {
console.log('value', value);
})
.then(value => { // 到这里就报错了,说then是undefined
console.log('value', value);
});

// TypeError: Cannot read property 'then' of undefined

在做这个需求之前,我们先捋一捋,先思考个问题,什么东西可以使用 then ?

答:Promise实例对象

因为then本来就是promise类的方法,只有promise的实例对象才拥有 then

那么,如何才能做到链式调用 then 呢?

答:then 每次被调用时,都返回一个Promise的实例对象。

那么我们来实现一下

then = (onFulfilled, onReject) => {
// 把我们之前的代码全部放到这个promise2中
let promise2 = new Promise((resolve, reject) => {
// 只有当前状态为成功fulfilled时才执行
if (this.state === FULFILLED) {
// 执行onFulfilled并把我们的value传递给它
onFulfilled(this.value);
}

// 只有当前状态为成功rejected时才执行
if (this.state === REJECTED) {
// 执行onReject并把我们的reason传递给它
onReject(this.reason);
}

// 只有当前状态为成功pending时才执行
if (this.state === PENDING) {
// 保存成功时的处理函数
this.onFulfilledCallback = onFulfilled;
// 保存失败时的处理函数
this.onRejectedCallback = onReject;
}
});

// 最后返回这个promise2实例对象
return promise2;
}

再次执行上一轮的测试,会发现,虽然不报错了,但是,我的 第二个 then 似乎没有被执行?

我们把代码改造一下:

class Promise {
// ....
onFulfilledCallback = []; // 成功时执行的函数
onRejectedCallback = []; // 失败时执行的函数

// ...

resolve = (value) => {
// 只有状态为pending时才可以resolve
if (this.state === PENDING) {
// ....
// 调用resolve修改状态为成功时,执行成功的处理函数
while (this.onFulfilledCallback.length) {
this.onFulfilledCallback.shift()();
}
}
}

reject = (reason) => {
// 只有状态为pending时才可以resolve
if (this.state === PENDING) {
// ....
// 调用reject修改状态为失败时,执行失败的处理函数
while (this.onRejectedCallback.length) {
this.onRejectedCallback.shift()();
}
}
}

// then中的onFulfilled实现
then = (onFulfilled, onReject) => {
// 返回一个Promise实例,实现链式调用的功能
let promise2 = new Promise((resolve, reject) => {
// 成功的处理函数
const onFulfilledCallback = () => {
// 执行onFulfilled并把我们的value传递给它
setTimeout(() => {
// 得到resolve或reject的返回值,将其赋值给变量x
const x = onFulfilled(this.value);
// 根据返回值类型的不同,进行不同的操作
this.resolvePromise(promise2, x, resolve, reject);
})
}

// 失败的处理函数
const onRejectedCallback = () => {
// 执行onReject并把我们的reason传递给它
setTimeout(() => {
// 得到resolve或reject的返回值,将其赋值给变量x
const x = onReject(this.reason);
// 根据返回值类型的不同,进行不同的操作
this.resolvePromise(promise2, x, resolve, reject);
})
}

// 只有当前状态为成功fulfilled时才执行
if (this.state === FULFILLED) {
// 执行成功处理函数
onFulfilledCallback();
}

// 只有当前状态为成功rejected时才执行
if (this.state === REJECTED) {
// 执行失败处理函数
onRejectedCallback();
}

// 只有当前状态为成功pending时才执行
if (this.state === PENDING) {
// 保存成功时的处理函数
this.onFulfilledCallback.push(onFulfilledCallback);
// 保存失败时的处理函数
this.onRejectedCallback.push(onRejectedCallback);
}
});

return promise2;
}

// 处理then的返回值
resolvePromise = (promise2, x, resolve, reject) => {
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {

} else {
resolve(x);
}
}
}

那么,上面这一大串代码,我们做了什么呢?

  1. 保存成功和失败状态处理函数的变量 改为数组
  2. resolve和reject在最后均通过循环遍历我们的状态处理函数数组,依次取出并执行。
  3. 成功处理函数失败处理函数单独封装,并将其放入定时器内执行。
  4. 增加了 **resolvePromise ** 这个类方法

为什么要这么做?

每当我们点一次 then,then函数都会被执行,且then的成功和失败处理函数我们也需要处理。

promise.then().then().then().then().then()...

这个代码会触发5次 then 方法

而且,上一个 then 的返回值

是下一个 then 的 resolve 参数

我们也说过了,只有promise调用了resolve的时候,才能进入then

那我们是不是返回了一个promise2

你返回了一个promise实例对象,可如果你这个实例对象不调用resolve,我能进入下一个 then吗?

不能!

那么怎么判断 then 有没有返回值呢?简单,onFulfilled 和 onRejected 就对应着 then 的2个方法,我可以用个 x 变量来接收。

接收到then的返回值后(如果没有主动return,就是undefined)

我又增加了一个类方法 resolvePromise 来判断,本次then执行结束,应该调用 resolve,还是调用 reject。

在 resolvePromise 中,根据promise A+ 规范,我们需要根据 x 的数据类型,进行不同的操作。

resolve = (promise2, x, resolve, reject) => {
// 如果x是对象或者函数
if(x !== null && (typeof x === 'object' || typeof x === 'function'))) {

} else {
// 来到这里,代表x是一个普通值类型,直接使用resolve把x给带走
resolve(x);
}
}

那为什么我要在定时器里写呢?

因为我们的promise2在执行到fulfilled和rejected的时候,promise2这个变量还没有初始化完毕呢,因此,我们使用定时器,把它推入事件队列中,等到下一轮事件循环的时候,就能拿到初始化后的promise2了。

then = (onFulfilled, onReject) => {
let promise2 = new Promise((resolve, reject) => {
if(this.state === FULFILLED) {
// 得到resolve或reject的返回值
const x = onFulfilled(this.value);
// 根据返回值类型的不同,进行不同的操作
this.resolvePromise(promise2, x, resolve, reject);
// TypeError报错,提示promise2在使用前还没有初始化……
}
});
return promise2;
}

说白了就是这个阶段如果不用定时器来延迟执行时机的话,我们无法拿到promsie2,因为此时的promise2还没有完成初始化,它还是一个 不存在的变量,所以我们需要使用定时器。

到了这时候,我们的promise链式调用功能就完成了

还是那句话,这一节有点小难,也有点绕,如果没有理解,建议先把这块内容理清楚!

完善resolvePromise

resolvePromise的作用是用于处理then里的返回值,假如你的返回值是普通值、对象、函数,我要怎么处理。

我们需要遵循 promise A+ 规范来实现!

来看下我们当前的代码

resolvePromise = (promise2, x, resolve, reject) => {
// 如果x是对象或者函数
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {

} else {
// 能进入这里,代表x是一个普通值
resolve(x);
}
}

根据 A+ 规范,如果x是对象或者函数,需要声明一个变量then,然后把x.then赋值给它,假如x身上没有then这个属性,则reject这个错误

resolvePromise = (promise2, x, resolve, reject) => {
// 如果x是对象或者函数
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
// 声明一个变量then
let then;
try {
// 取出x.then并赋值给then(假如x被设置了不可读,则可能会报错,所以需要try/catch)
then = x.then;
} catch (err) {
// 失败,reject
reject(err);
}
} else {
// 能进入这里,代表x是一个普通值
resolve(x);
}
}

接下来,我们需要 判断这个变量then是不是一个函数

如果then是一个函数,则

  1. 修改then的this指向为x
  2. 传递2个参数(这2个参数其实就是对应then方法的两个形参)
    1. y : 相当于 then 的resolve方法,被调用时执行 resolvePromise
    2. r : 相当于 then 的reject方法
    3. 如果 yr 都被调用了,或者被调用了多次,则只第一次有效,后面的忽略。
    4. 如果在调用then时抛出了异常,则:
      1. 如果 yr 已经被调用了,则忽略它。
      2. 否则, 以e为reason将 promise 拒绝。

如果then不是函数,则

  1. 以x为值,调用resolve

代码实现

// 如果x是对象或者函数
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
// 声明一个变量then
let then;
// 声明一个变量called,代表y或r是否被调用过
let called = false; // false代表没有被调用过
try {
// 取出x.then并赋值给then(假如x被设置了不可读,则可能会报错,所以需要try/catch)
then = x.then;
} catch (err) {
// 失败,reject
reject(err);
}

// 判断then是否是一个函数
if (typeof then === 'function') {
try {
// 修改then的this指向为x
then.call(
x,
y => {
// 如果y或x已经被调用过,则直接退出
if (called) return;
// 修改called为已调用
called = true;
// 再次执行resolvePromise
this.resolvePromise(promise2, y, resolve, reject);
},
r => {
// 如果y或x已经被调用过,则直接退出
if (called) return;
// 修改called为已调用
called = true;
// reject这个r
reject(r);
}
)
} catch (e) {
// 如果then在被调用的过程中出错,则会进入这里,直接reject
reject(e);
}
} else {
// 如果then不是一个函数,则以x进行resolve
resolve(x);
}
} else {
// x不是对象,也不是函数,则以x进行resolve
resolve(x);
}

到此为止,我们的resolvePromise方法就完成了

异常处理

为了避免代码执行过程中出现错误,进而导致程序崩溃,我们需要在可能会出现错误的地方进行容错处理

**成功处理函数增加 try/catch **

// 成功的处理函数
const onFulfilledCallback = () => {
// 执行onFulfilled并把我们的value传递给它
setTimeout(() => {
try {
// 得到resolve的返回值
const x = onFulfilled(this.value);
// 根据返回值类型的不同,进行不同的操作
this.resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
})
}

**失败处理函数增加 try/catch **

// 失败的处理函数
const onRejectedCallback = () => {
// 执行onReject并把我们的reason传递给它
setTimeout(() => {
try {
// 得到reject的返回值
const x = onReject(this.reason);
// 根据返回值类型的不同,进行不同的操作
this.resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
})
}

增加catch方法

在原生promise的实例对象中是有catch这么一个方法的,它一般写在链式调用的最后面,看个例子

new Promise((resolve, reject) => {
resolve(1);
})
.then(value => {
return Promise.reject('这是一个错误信息');
})
.catch(err => {
console.log('err', err);
})

假如then里没有对错误进行捕获处理,则错误信息会被最后的catch给捕获。

我们来实现一下,实现代码也比较简单

catch = (onRejected) => {
// 其实就是调用then方法,然后只传递reject的处理方法
return this.then(null, onRejected);
}

其它

then方法的两个参数是可选的,可以传,也可以不传。

我们也来实现一下,使得它们变为可选参数。

注意:遵循promise A+ 规范

then = (onFulfilled, onRejected) => {
// 如果onFulfilled不是一个函数,则给它一个默认函数
if (typeof onFulfilled !== 'function') onFulfilled = value => value;
// 如果onRejected不是一个函数,则给它一个默认函数,行为是抛出reason错误信息
if (typeof onRejected !== 'function') onRejected = reason => { throw reason };
}

不理解为什么这么做的同孩,需要多看几遍,多分析几遍

到此为止,我们的promise就已经实现完了

我们可以看到,promise的实现中,then方法是最复杂的

但其实,只要你多看几遍,会发现其实也没有想象中那么难


实现静态resolve

我们来看下原生promise的例子

new Promise((resolve, reject) => {
resolve(1);
}).then(value => {
return Promise.resolve(2);
}).then(value => {
console.log(value); // 2
})

我们可以看到,上面这个例子中的 resolve 是一个静态方法,返回的是一个成功状态的promise,这样我们才可以继续向后点出then。

那么,我们来实现一下,实现过程还是很简单的。

static resolve = (value) => {
return new Promise((resolve, reject) => {
resolve(value);
})
}

对,你没看错,就是这么简单。

接收到用户传递的参数,随后创建一个promise对象,调用该实例对象的resolve(value) 出去,perfect!

实现静态reject

既然有静态resolve,那自然也有静态reject。

实现的过程与静态resolve几乎一样。

static reject = (reason) => {
return new Promise((resolve, reject) => {
reject(reason);
})
}

实现静态all

我们看个原生的例子

let promises = [...];
Promise
.all(promises)
.then(value => {
console.log(value);
})

不了解Promise.all的同学,请自行去百度,这里不会细讲。

promise.all方法通常用来实现并发,例如并发请求等。

同时,它的特性是:所有promise的状态都为成功,才是成功,只要有一个promise是失败的,则整体全部失败

我们来实现一下

static all = (promises) => {
let result = [];
let count = 0;

// 判断参数是否是一个数组,如果不是数组,则不执行,直接返回该参数
if (!Array.isArray(promises)) return promises;

return new Promise((resolve, reject) => {
// 往result里添加数据
const insertData = (data, index) => {
result[index] = data;
count++;
// 判断是否执行完毕
if(count === result.length) {
resolve(result);
}
}

// 使用循环遍历所有promise并执行
for(let i = 0; i < promises.length; i++) {
promises[i].then(value => insertData(value, i), reject);
}
})
}

实现静态race

race与all特性差不多,区别在于:

只要有一个promise的状态是成功,整体就是整个,只有所有promise都是失败时,才是失败

实现代码

static race = (promises) => {
if (!Array.isArray(promises)) return promises;
return new Promise((resolve, reject) => {
for(let i = 0; i < promises.length; i++) {
promises[i].then(resolve, reject);
}
})
}

A+规范测试

我们的promise已经全部实现完了,那么,我们来测试下我们的代码,是否符合promise A+ 规范吧

为了进行代码测试,我们需要往我们的Promise类中增加一个静态方法(它只用来做测试,测完可以删除

// 全部复制,啥也不用改
static deferred = function () {
let result = {};
result.promise = new Promise(function (resolve, reject) {
result.resolve = resolve;
result.reject = reject;
});

return result;
}

接下来,把我们写的Promise类给导出(commonJS规范

module.exports = Promise;

最后,执行测试,在我们文件所在的目录下,打开命令行工具,输入以下命令

npx promises-aplus-tests .\xxx.js

其中的 xxx.js 就是你的文件名,就是我们写的这个Promise文件

我测试了一下,所有代码全部通过了测试,舒服~


完整代码

const PENDING = 'pending'; // pending等待状态
const FULFILLED = 'fulfilled'; // resolve成功状态
const REJECTED = 'rejected'; // reject失败状态

class Promise {
state = PENDING; // promise的初始状态,也就是默认状态是pending
value = null; // resolve的value
reason = null; // reject的reason
onFulfilledCallback = []; // 成功时执行的函数
onRejectedCallback = []; // 失败时执行的函数

constructor(executor) {
executor(this.resolve, this.reject);
}

resolve = (value) => {
// 只有状态为pending时才可以resolve
if (this.state === PENDING) {
// 修改状态为fulfilled
this.state = FULFILLED;
this.value = value;
// 调用resolve修改状态为成功时,执行成功的处理函数
while (this.onFulfilledCallback.length) {
this.onFulfilledCallback.shift()();
}
}
}

reject = (reason) => {
// 只有状态为pending时才可以resolve
if (this.state === PENDING) {
// 修改状态为rejected
this.state = REJECTED;
this.reason = reason;
// 调用reject修改状态为失败时,执行失败的处理函数
while (this.onRejectedCallback.length) {
this.onRejectedCallback.shift()();
}
}
}

then = (onFulfilled, onRejected) => {
// 如果onFulfilled不是一个函数,则给它一个默认函数
if (typeof onFulfilled !== 'function') onFulfilled = value => value;
// 如果onRejected不是一个函数,则给它一个默认函数,行为是抛出reason错误信息
if (typeof onRejected !== 'function') onRejected = reason => { throw reason };

let promise2 = new Promise((resolve, reject) => {
// 成功的处理函数
const onFulfilledCallback = () => {
// 执行onFulfilled并把我们的value传递给它
setTimeout(() => {
try {
// 得到resolve的返回值
const x = onFulfilled(this.value);
// 根据返回值类型的不同,进行不同的操作
this.resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
})
}

// 失败的处理函数
const onRejectedCallback = () => {
// 执行onRejected并把我们的reason传递给它
setTimeout(() => {
try {
// 得到reject的返回值
const x = onRejected(this.reason);
// 根据返回值类型的不同,进行不同的操作
this.resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
})
}

// 只有当前状态为成功fulfilled时才执行
if (this.state === FULFILLED) {
onFulfilledCallback();
}

// 只有当前状态为成功rejected时才执行
if (this.state === REJECTED) {
onRejectedCallback();
}

// 只有当前状态为成功pending时才执行
if (this.state === PENDING) {
// 保存成功时的处理函数
this.onFulfilledCallback.push(onFulfilledCallback);
// 保存失败时的处理函数
this.onRejectedCallback.push(onRejectedCallback);
}
});

return promise2;
}

resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x) reject(new TypeError(`循环引用错误`));
// 如果x是对象或者函数
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
// 声明一个变量then
let then;
// 声明一个变量called,代表y或r是否被调用过
let called = false; // false代表没有被调用过
try {
// 取出x.then并赋值给then(假如x被设置了不可读,则可能会报错,所以需要try/catch)
then = x.then;
} catch (err) {
// 失败,reject
reject(err);
}

// 判断then是否是一个函数
if (typeof then === 'function') {
try {
// 修改then的this指向为x
then.call(
x,
y => {
// 如果y或x已经被调用过,则直接退出
if (called) return;
// 修改called为已调用
called = true;
// 再次执行resolvePromise
this.resolvePromise(promise2, y, resolve, reject);
},
r => {
// 如果y或x已经被调用过,则直接退出
if (called) return;
// 修改called为已调用
called = true;
// reject这个r
reject(r);
}
)
} catch (e) {
// 如果y或x已经被调用过,则直接退出
if (called) return;
// 如果then在被调用的过程中出错,则会进入这里,直接reject
reject(e);
}
} else {
// 如果then不是一个函数,则以x进行resolve
resolve(x);
}
} else {
// x不是对象,也不是函数,则以x进行resolve
resolve(x);
}
}

static resolve = (value) => {
return new Promise((resolve, reject) => {
resolve(value);
})
}

static reject = (reason) => {
return new Promise((resolve, reject) => {
reject(reason);
})
}

static all = (promises) => {
let result = [];
let count = 0;

// 判断参数是否是一个数组,如果不是数组,则不执行,直接返回该参数
if (!Array.isArray(promises)) return promises;

return new Promise((resolve, reject) => {
// 往result里添加数据
const insertData = (data, index) => {
result[index] = data;
count++;
// 判断是否执行完毕
if (count === result.length) {
resolve(result);
}
}

// 使用循环遍历所有promise并执行
for (let i = 0; i < promises.length; i++) {
promises[i].then(value => insertData(value, i), reject);
}
})
}

static race = (promises) => {
if (!Array.isArray(promises)) return promises;
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(resolve, reject);
}
})
}
}
-------------本文结束    感谢阅读-------------
坚持原创技术分享,您的支持将鼓励我继续创作!