首先应该了解,Promise具有哪些特点,以此梳理出需要实现的需求点,这里先实现一些比较基础的方法,主要有以下几点:
- 实现resolve和reject回调
- 状态不可变
- 实现throw抛出异常
- 实现then方法
- 实现then的链式调用
- 微任务
实现resolve和reject回调
先来看一段代码
let p1 = new Promise((resolve, reject) => {
resolve('success');
})
console.log(p1);
let p2 = new Promise((resolve, reject) => {
reject('fail');
})
console.log(p2);
控制台输出:
从上面两段代码可以看出resolve()执行的是成功的回调,并且执行resolve方法后Promise状态会由pending变为fulfilled,相反,reject()执行的是失败的回调,执行reject方法后Promise状态会由pending变为rejected,知道了这一点就可以开始撸代码啦~
class myPromise {
constructor(excutor) {
//初始化
this.promiseState = 'pending';
this.promiseResult = null;
this.resolve = this.resolve.bind(this);
this.reject = this.reject.bind(this);
excutor(this.resolve, this.reject);
}
resolve(val) {
this.promiseState = 'fulfilled';
this.promiseResult = val;
}
reject(reason) {
this.promiseState = 'rejected';
this.promiseResult = reason;
}
}
let p = new myPromise((resolve, reject) => {
resolve('success')
})
console.log(p);
运行一下代码:
状态不可变
上面已经初步实现了resolve和reject回调,也进行了代码测试,那么如果把代码改成下面那样,会发生什么事情呢?
let p = new myPromise((resolve, reject) => {
resolve('success');
reject('fail');
})
输出结果:
从上面的代码运行结果看,myPromise状态为rejected,也就是说myPromise的状态是可以改变的,那么怎样才能实现状态不可变呢?
很简单,在执行resolve和reject方法前加个判断
class myPromise {
constructor(excutor) {
//初始化
this.promiseState = 'pending';
this.promiseResult = null;
this.resolve = this.resolve.bind(this);
this.reject = this.reject.bind(this);
excutor(this.resolve, this.reject);
}
resolve(val) {
if (this.promiseState !== 'pending') return;
this.promiseState = 'fulfilled';
this.promiseResult = val;
}
reject(reason) {
if (this.promiseState !== 'pending') return;
this.promiseState = 'rejected';
this.promiseResult = reason;
}
}
再次执行上述代码:
实现throw抛出异常
let p = new Promise((resolve, reject) => {
throw ('fail')
})
console.log(p);
上面的代码会输出什么呢?
可以看出,Promise中抛出一个异常,相当于执行了Promise中的reject方法
下面就来实现一下
constructor(excutor) {
//初始化
this.promiseState = 'pending';
this.promiseResult = null;
this.resolve = this.resolve.bind(this);
this.reject = this.reject.bind(this);
try {
excutor(this.resolve, this.reject);
} catch (err) {
this.reject(err);
}
}
将代码改成上面那样,通过try…catch捕捉异常,然后调用reject方法返回,最后验证一下代码:
let p = new myPromise((resolve, reject) => {
throw ('fail');
})
console.log(p);
实现then方法
then方法接收两个回调,一个是成功回调,一个是失败回调。当Promise状态为fulfilled时,执行成功回调,rejected时执行失败回调。
then(onFulfilled, onRejected) {
if (this.promiseState === 'fulfilled') {
onFulfilled(this.promiseResult);
}
if (this.promiseState === 'rejected') {
onRejected(this.promiseResult);
}
}
验证一下代码:
let p = new myPromise((resolve, reject) => {
resolve('success');
})
p.then(res => {
console.log("res输出:", res);
})
then的链式调用
//链式调用
let p3 = new Promise((resolve, reject) => {
resolve(10);
}).then(res => {
return res * 2
}).then(res => {
console.log('res:', res);
}, err => {
console.log('err:', err);
}) // 输出20
//链式调用
let p3 = new Promise((resolve, reject) => {
resolve(10);
}).then(res => {
return new Promise((resolve, reject) => {
reject('fail');
})
}).then(res => {
console.log('res:', res);
}, err => {
console.log('err:', err);
}) // 输出fail
从上面的代码中可以总结出:
- then可以链式调用,即then方法本身会返回一个新的Promise
- 上一个then的返回值会影响下一个then的执行结果:
当返回值是一个Promise对象,返回值为成功,则then执行成功
当返回值是一个Promise对象,返回值为失败,则then执行失败
当返回值不是一个Promise对象,返回值为成功,then执行成功
微任务
再来看一段代码:
let promise = new Promise((resolve, reject) => {
console.log(2);
resolve(2);
})
promise.then(res => res * 2).then(res => {
console.log('res:', res)
})
console.log(3);
//结果输出:
// 2
// 3
// res:4
Promise中的then是微任务,不了解什么是微任务的同学可以先去了解下js运行机制
这里就用一种最简单的方式实现一下
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
onRejected = typeof onRejected === 'function' ? onRejected : reson => { throw reson };
setTimeout(() => {
const thenPromise = new myPromise((resolve, reject) => {
if (this.promiseState === 'fulfilled') {
let x = onFulfilled(this.promiseResult);
argsType(x, resolve, reject);
}else if (this.promiseState === 'rejected') {
let x = onRejected(this.promiseResult);
argsType(x, resolve, reject);
}
})
return thenPromise;
})
}
// 判断x的类型
function argsType(x, resolve, reject){
if(x instanceof myPromise){
// x是promise
then(resolve,reject);
}else{
// x不是promise
resolve(x);
}
}