加深对 promise 的理解,一步步实现并完善 promise 及API实现。
resolve 和 reject 实现
resolve 和 reject 用来决定 new Promise
后 promise 对象的状态的,两个函数在代码中的先后顺序决定了 promise 对象的状态。一旦状态改变则不再修改
实现的难点在于状态改变后无法再次修改 promise 的状态。
// promise 中 resolve/reject 执行的例子
console.log('start')
const p1 =new Promise((resolve,reject)=>{
console.log("doing")
resolve(1)
reject(2)
})
console.log('end',p1)
// start
// doing
// end Promise {<fulfilled>: 1}
// 手动实现
class MPromise{
static PENDINGSTATUS ='pending'
static FULFILLESSTATUS = 'fulfilled'
static REJECTEDSTATUS = 'rejected'
constructor(executor){
this.PromiseState = MPromise.PENDINGSTATUS;
this.PromiseResult = null;
// resolve 和 reject 执行时 this 的值为 window,需要绑定 this
executor(this.resolve.bind(this),this.reject.bind(this))
}
resolve(res){
if(this.PromiseState === MPromise.PENDINGSTATUS){
this.PromiseResult = res;
this.PromiseState = MPromise.FULFILLESSTATUS;
}
}
reject(err){
if(this.PromiseState === MPromise.PENDINGSTATUS){
this.PromiseResult = err;
this.PromiseState = MPromise.REJECTEDSTATUS;
}
}
}
console.log('start')
const p2 =new MPromise((resolve,reject)=>{
console.log("doing")
resolve(1)
reject(2)
})
console.log('end',p2)
// start
// doing
// end MPromise { PromiseState: 'fulfilled', PromiseResult: 1 }
复制代码
Promise.prototype.then 的实现
基本用法
说明
- 异步执行
- 构造函数的参数 executor 执行时调用 resolve ,then 执行 onFulfilled
- 构造函数的参数 executor 执行时调用 reject ,then 执行 onRejected
// 示例
console.log('start')
const p1 = new Promise((resolve, reject) => {
resolve(1)
}).then(res => {
console.log('p1->then', res)
})
const p2 = new Promise((resolve, reject) => {
reject(2)
}).then(res => { }, err => {
console.log('p2->then', err)
})
console.log('end')
// start
// end
// p1->then 1
// p2->then 2
复制代码
实现思路:
- then 函数用来注册回调函数,将要执行的 onFulfilled, onRejected 回调函数加入到队列中
- resolve/reject 函数异步执行回调函数
以 new Promise(resolve=>resolve(1)).then(res=>res)
为例说明实现过程
-
pending状态:执行同步代码
- 执行
resolve=>resolve(1)
函数 ,执行resolve(1)
函数 - 需要执行的代码封装成函数 fn 加入到微任务中,该函数功能包括:状态修改为 fulfilled ,PromiseResult 值修改,执行 resolvedQueue 队列中的函数
- 执行
then(res=>res)
函数,添加 onFulfilled 函数即res=>res
到队列数组 resolvedQueue 中
- 执行
-
pending → fulfilled 状态:微任务中的 fn 异步执行
- 状态修改为 fulfilled
- PromiseResult 值修改
- resolvedQueue 队列中的数组依次执行
class MPromise {
static PENDINGSTATUS = 'pending'
static FULFILLESSTATUS = 'fulfilled'
static REJECTEDSTATUS = 'rejected'
constructor(executor) {
this.PromiseState = MPromise.PENDINGSTATUS;
this.PromiseResult = null;
// +++ 以下代码块为新增
// 存放then 函数中需要执行的 onFulfilled, onRejected 回调函数
this.resolvedQueue = [];
this.rejectedQueue = [];
// +++
// resolve 和 reject 执行时 this 的值为 window,需要绑定 this
executor(this.resolve.bind(this), this.reject.bind(this));
}
resolve(res) {
if (this.PromiseState === MPromise.PENDINGSTATUS) {
// 通过if 判断状态,实现无法再次修改 promise 的状态
// +++ 以下代码块为新增
// 修改状态(此处为异步),异步执行 resolvedQueue 队列中保存的 onFulfilled 函数
const fn = () => {
this.PromiseResult = res;
this.PromiseState = MPromise.FULFILLESSTATUS;
this.resolvedQueue.length && this.resolvedQueue.forEach(cb => cb(res))
}
// 开启微队列
resultHandlerAsync(fn)
// +++
}
}
reject(err) {
if (this.PromiseState === MPromise.PENDINGSTATUS) {
// +++ 以下代码块为新增
// 异步执行 rejectedQueue 队列中保存的 onRejected 函数
const fn = () => {
this.PromiseResult = err;
this.PromiseState = MPromise.REJECTEDSTATUS;
this.rejectedQueue.length && this.rejectedQueue.forEach(cb => cb(err))
}
// 开启微队列
resultHandlerAsync(fn)
// +++
}
}
// +++ 以下代码块为新增
then(onFulfilled, onRejected) {
// then 函数用来注册回调函数,将要执行的 onFulfilled, onRejected 回调函数加入到队列中
if (this.PromiseState === MPromise.PENDINGSTATUS) {
this.resolvedQueue.push(onFulfilled)
this.rejectedQueue.push(onRejected)
}
}
// +++
}
// 测试
console.log('start')
const p3 = new MPromise((resolve, reject) => {
resolve(1)
}).then(res => {
console.log('p3->then', res)
})
const p4 = new MPromise((resolve, reject) => {
reject(2)
}).then(res => { }, err => {
console.log('p4->then', err)
})
console.log('end')
// start
// end
// p3->then 1
// p4->then 2
复制代码
then 的链式调用
需要实现的功能如下:
- onFulfilled, onRejected 回调函数执行后返回值或者 Error 作为参数传递给下个 onFulfilled, onRejected
- then 执行后仍然是一个 promise 对象
// 示例
console.log('start')
new Promise(resolve => {
resolve(1)
})
.then(res => res + 1)
.then(res => {
console.log("resolve(1) ~ then:return 1+1 ~ then: res", res)
})
new Promise(resolve => {
resolve(2)
})
.then(res => { throw new Error(res + 1) })
.then(res => { console.log(res) }, err => {
console.log("resolve(2) ~ then:throw Err 2+1 ~ then: err", err)
})
new Promise((resolve, reject) => {
reject(3)
})
.then(() => { }, err => err + 1)
.then(res => {
console.log("reject(3) ~ then:return 3+1 ~ then: res", res)
})
new Promise((resolve, reject) => {
reject(4)
})
.then(() => { },err => { throw new Error(err+1) })
.then(res => { console.log(res) }, err => {
console.log("reject(4) ~ then:throw Err 4+1 ~ then: err", err)
})
console.log('end')
// start
// end
// resolve(1) ~ then:return 1+1 ~ then: res 2
// resolve(2) ~ then:throw Err 2+1 ~ then: err Error: 3
// reject(3) ~ then:return 3+1 ~ then: res 4
// reject(4) ~ then:throw Err 4+1 ~ then: err Error: 5
复制代码
实现思路:
- then 新建一个 promise,并返回
- push 到 resolvedQueue/rejectedQueue 的函数包括两步,执行 onFulfilled/onRejected 和 resolve /reject。
以 new Promise(resolve=>resolve(1)).then(res=>res+1).then(res=>console.log(res))
为例说明实现过程
-
pending状态:执行同步代码
new Promise
执行:resolve=>resolve(1)
执行resolve(1)
执行:需要执行的代码封装成函数 fn 加入到微任务中,fn 函数功能包括:状态修改为 fulfilled ,PromiseResult 值修改,执行 resolvedQueue 队列中的函数- then 执行: 创建 promise,添加函数队列数组 resolvedQueue 中,该函数的作用包括执行 onFulfilled/onRejected 和 resolve /reject(参数为onFulfilled/onRejected的返回值)
class MPromise {
static PENDINGSTATUS = 'pending'
static FULFILLESSTATUS = 'fulfilled'
static REJECTEDSTATUS = 'rejected'
constructor(executor) {
this.PromiseState = MPromise.PENDINGSTATUS;
this.PromiseResult = null;
// 存放then 函数中需要执行的 onFulfilled, onRejected 回调函数
this.resolvedQueue = [];
this.rejectedQueue = [];
// resolve 和 reject 执行时 this 的值为 window,需要绑定 this
executor(this.resolve.bind(this), this.reject.bind(this));
}
resolve(res) {
// +++ 以下代码有修改
if (this.PromiseState === MPromise.PENDINGSTATUS) {
// 通过if 判断状态,实现无法再次修改 promise 的状态
// 异步执行 resolvedQueue 队列中保存的 onFulfilled 函数
// 开启微队列
resultHandlerAsync(() => {
this.PromiseResult = res;
this.PromiseState = MPromise.FULFILLESSTATUS;
if (this.resolvedQueue.length) {
const cb = this.resolvedQueue.shift();
cb(res)
}
})
}
// +++
}
reject(err) {
// +++ 以下代码有修改
if (this.PromiseState === MPromise.PENDINGSTATUS) {
// 异步执行 rejectedQueue 队列中保存的 onRejected 函数
// 开启微队列
resultHandlerAsync(() => {
this.PromiseResult = err;
this.PromiseState = MPromise.REJECTEDSTATUS;
if (this.rejectedQueue.length) {
const cb = this.rejectedQueue.shift();
cb(err)
}
})
}
// +++
}
then(onFulfilled, onRejected) {
// then 函数用来注册回调函数,将要执行的 onFulfilled, onRejected 回调函数加入到队列中
// +++ 以下代码有修改
return new MPromise((resolve, reject) => {
if (this.PromiseState === MPromise.PENDINGSTATUS) {
// 改写目的:实现 onFulfilled 返回值,均会传递给下一次的 then 中 onFulfilled的参数
this.resolvedQueue.push((res) => {
try {
const result = onFulfilled(res);
resolve(result);
} catch (err) {
reject(err)
}
});
this.rejectedQueue.push((err) => {
try {
const result = onRejected(err);
resolve(result);
} catch (err) {
reject(err)
}
});
}
})
// +++
}
}
function resultHandlerAsync(cb) {
// console.log('async')
// 此函数会开启一个微任务,cb 放入到微任务中执行
const observer = new MutationObserver(cb);
observer.observe(document.body, { attributes: true });
document.body.className = `${Math.random()}`;
}
console.log('start')
new MPromise(resolve => {
resolve(1)
})
.then(res => res + 1)
.then(res => {
console.log("resolve(1) ~ then:return 1+1 ~ then: res", res)
})
new MPromise(resolve => {
resolve(2)
})
.then(res => { throw new Error(res + 1) })
.then(res => { console.log(res) }, err => {
console.log("resolve(2) ~ then:throw Err 2+1 ~ then: err", err)
})
new MPromise((resolve, reject) => {
reject(3)
})
.then(() => { }, err => err + 1)
.then(res => {
console.log("reject(3) ~ then:return 3+1 ~ then: res", res)
})
new MPromise((resolve, reject) => {
reject(4)
})
.then(() => { },err => { throw new Error(err+1) })
.then(res => { console.log(res) }, err => {
console.log("reject(4) ~ then:throw Err 4+1 ~ then: err", err)
})
console.log('end')
// start
// end
// resolve(1) ~ then:return 1+1 ~ then: res 2
// resolve(2) ~ then:throw Err 2+1 ~ then: err Error: 3
// reject(3) ~ then:return 3+1 ~ then: res 4
// reject(4) ~ then:throw Err 4+1 ~ then: err Error: 5
复制代码
then 的参数非函数
// 示例
new Promise((resolve, reject) => {
resolve(1)
}).then().then(res => { console.log("resolve(1) ~ undefined ~ then: res", res) })
new Promise((resolve, reject) => {
reject(2)
}).then().then(undefined, err => { console.log("reject(2) ~ undefined ~ then: err", err) })
// resolve(1) ~ undefined ~ then: res 1
// reject(2) ~ undefined ~ then: err 2
复制代码
实现思路:
判断传入的参数是否为函数,如果是函数不做任何处理;如果不是函数,创建一个函数,该函数功能是直接返回resolve 改变的值或者抛出错误
then(onFulfilled, onRejected) {
// +++ 以下代码为新增
onFulfilled = (typeof onFulfilled === 'function') ? onFulfilled : res => res;
onRejected = (typeof onRejected === 'function') ? onRejected : err => { throw err };
// +++
return new MPromise(...)
}
new MPromise((resolve, reject) => {
resolve(1)
}).then().then(res => { console.log("resolve(1) ~ undefined ~ then: res", res) })
new MPromise((resolve, reject) => {
reject(2)
}).then().then(undefined, err => { console.log("reject(2) ~ undefined ~ then: err", err) })
// resolve(1) ~ undefined ~ then: res 1
// reject(2) ~ undefined ~ then: err 2
复制代码
Promise.prototype.catch 和 Promise.prototype.finally 的实现
catch 方法返回一个Promise ,并且处理拒绝的情况。
finally方法返回一个Promise。在promise结束时,无论结果是fulfilled或者是rejected,都会执行指定的回调函数
// 示例
new Promise((resolve, reject) => {
reject(1)
})
.catch(err => {
console.log("reject(1) ~ then: err", err)
})
new Promise((resolve, reject) => {
reject(2)
})
.catch()
.then(() => { }, err => {
console.log("reject(2) ~ catch:undefined ~ then: err", err)
})
new Promise((resolve, reject) => {
reject(3)
})
.catch(err => err + 1)
.finally((value) => {
console.log("reject(3) ~ catch: err=>err+1 ~ finally:return 22", value);
return 22;
})
.then(res => {
console.log("reject(3) ~ catch: err=>err+1 ~ finally:return 22 ~ then: err", res)
})
// reject(1) ~ then: err 1
// reject(2) ~ catch:undefined ~ then: err 2
// reject(3) ~ catch: err=>err+1 ~ finally:return 22 undefined
// reject(3) ~ catch: err=>err+1 ~ finally:return 22 ~ then:err 4
复制代码
实现:
catch 方法相当于 then(undefined,onRejected)
finally 方法:异步执行传递的回调参数,同时将上一个 then 的结果传递到下一个
catch(onRejected) {
return this.then(undefined,onRejected)
}
finally(cb){
return new MPromise((resolve,reject)=>{
if (this.PromiseState === MPromise.PENDINGSTATUS) {
this.resolvedQueue.push((res) => {
try {
cb()
resolve(res);
} catch (err) {
reject(err)
}
});
this.rejectedQueue.push((err) => {
try {
cb();
resolve(err);
} catch (err) {
reject(err)
}
});
}
})
}
new MPromise((resolve, reject) => {
reject(1)
})
.catch(err => {
console.log("reject(1) ~ then: err", err)
})
new MPromise((resolve, reject) => {
reject(2)
})
.catch()
.then(() => { }, err => {
console.log("reject(2) ~ catch:undefined ~ then: err", err)
})
new MPromise((resolve, reject) => {
reject(3)
})
.catch(err => err + 1)
.finally((value) => {
console.log("reject(3) ~ catch: err=>err+1 ~ finally:return 22", value);
return 22;
})
.then(res => {
console.log("reject(3) ~ catch: err=>err+1 ~ finally:return 22 ~ then: err", res)
})
// reject(1) ~ then: err 1
// reject(2) ~ catch:undefined ~ then: err 2
// reject(3) ~ catch: err=>err+1 ~ finally:return 22 undefined
// reject(3) ~ catch: err=>err+1 ~ finally:return 22 ~ then:err 4
复制代码
Promise.resolve 和 Promise.reject 实现
Promise.resolve 方法返回一个以给定值解析后的 Promise 对象
Promise.reject 方法返回一个带有拒绝原因的 Promise 对象
实现方式
static resolve(res) {
return new MPromise(resolve => resolve(res))
}
static reject(res) {
return new MPromise((resolve, reject) => reject(res))
}
复制代码
Promise.all 和 Promise.race 实现
Promise.all() 方法接收一个 promise 的 可迭代类型(Array,Map,Set),并且只返回一个 Promise 对象。返回值为所有 resolve 的结果,如果出现任何一个 reject 的回调执行,则会立即抛出错误。
Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。
// 示例
const p1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, 'one');
});
const p2 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'two');
});
const p3 = new Promise((resolve, reject) => {
setTimeout(reject, 300, 'three');
});
Promise.race([p1, p2]).then((value) => {
console.log('Promise.race', value);
});
Promise.all([p1, p2, p3]).then((value) => {
console.log('Promise.all ~ then:res', value);
}).catch(err=>{console.log('Promise.all ~ catch:err', err)});
Promise.all([p1, p2]).then((value) => {
console.log('Promise.all', value);
});
// Promise.race two
// Promise.all ~ catch:err three
// Promise.all ['one', 'two']
复制代码
static race(promiseList) {
return new MPromise((resolve, reject) => {
promiseList.forEach(p => p.then(res => resolve(res), err => reject(err)))
})
}
static all(promiseList) {
return new MPromise((resolve, reject) => {
let promiseArr = [];
promiseList.forEach(p => {
p.then(res => {
promiseArr.push(res)
}, err => {
throw new Error(err);
reject(err);
})
})
resolve(promiseArr);
})
}
复制代码
完整代码
class MPromise {
static PENDINGSTATUS = 'pending'
static FULFILLESSTATUS = 'fulfilled'
static REJECTEDSTATUS = 'rejected'
constructor(executor) {
this.PromiseState = MPromise.PENDINGSTATUS;
this.PromiseResult = null;
// 存放then 函数中需要执行的 onFulfilled, onRejected 回调函数
this.resolvedQueue = [];
this.rejectedQueue = [];
// resolve 和 reject 执行时 this 的值为 window,需要绑定 this
executor(this.resolve.bind(this), this.reject.bind(this));
}
resolve(res) {
// console.log('resolve')
if (this.PromiseState === MPromise.PENDINGSTATUS) {
// 通过if 判断状态,实现无法再次修改 promise 的状态
// 异步执行 resolvedQueue 队列中保存的 onFulfilled 函数
// 开启微队列
resultHandlerAsync(() => {
this.PromiseResult = res;
this.PromiseState = MPromise.FULFILLESSTATUS;
if (this.resolvedQueue.length) {
const cb = this.resolvedQueue.shift();
cb(res)
}
})
}
}
reject(err) {
if (this.PromiseState === MPromise.PENDINGSTATUS) {
// 异步执行 rejectedQueue 队列中保存的 onRejected 函数
// 开启微队列
resultHandlerAsync(() => {
this.PromiseResult = err;
this.PromiseState = MPromise.REJECTEDSTATUS;
if (this.rejectedQueue.length) {
const cb = this.rejectedQueue.shift();
cb(err)
}
})
}
}
then(onFulfilled, onRejected) {
// then 函数用来注册回调函数,将要执行的 onFulfilled, onRejected 回调函数加入到队列中
onFulfilled = (typeof onFulfilled === 'function') ? onFulfilled : res => res;
onRejected = (typeof onRejected === 'function') ? onRejected : err => { throw err };
return new MPromise((resolve, reject) => {
if (this.PromiseState === MPromise.PENDINGSTATUS) {
// 改写目的:实现 onFulfilled 返回值,均会传递给下一次的 then 中 onFulfilled的参数
this.resolvedQueue.push((res) => {
try {
const result = onFulfilled(res);
resolve(result);
} catch (err) {
reject(err)
}
});
this.rejectedQueue.push((err) => {
try {
const result = onRejected(err);
resolve(result);
} catch (err) {
reject(err)
}
});
}
})
}
catch(onRejected) {
return this.then(undefined, onRejected)
}
finally(cb) {
return new MPromise((resolve, reject) => {
if (this.PromiseState === MPromise.PENDINGSTATUS) {
// 改写目的:实现 onFulfilled 返回值,均会传递给下一次的 then 中 onFulfilled的参数
this.resolvedQueue.push((res) => {
try {
cb()
resolve(res);
} catch (err) {
reject(err)
}
});
this.rejectedQueue.push((err) => {
try {
cb();
resolve(err);
} catch (err) {
reject(err)
}
});
}
})
}
static resolve(res) {
return new MPromise(resolve => resolve(res))
}
static reject(res) {
return new MPromise((resolve, reject) => reject(res))
}
static race(promiseList) {
return new MPromise((resolve, reject) => {
promiseList.forEach(p => p.then(res => resolve(res), err => reject(err)))
})
}
static all(promiseList) {
return new MPromise((resolve, reject) => {
let promiseArr = [];
promiseList.forEach(p => {
p.then(res => {
promiseArr.push(res)
}, err => {
throw new Error(err);
reject(err);
})
})
resolve(promiseArr);
})
}
}
function resultHandlerAsync(cb) {
// 此函数会开启一个微任务,cb 放入到微任务中执行
const observer = new MutationObserver(cb);
observer.observe(document.body, { attributes: true });
document.body.className = `${Math.random()}`;
}
复制代码