Promise
异步神器Promise众所周知,解决了异步回调地狱问题,当然,在面试中也会问到一些实现原理或者让你 please write a Promise
- 先来一个简单版的Promise
回调特征:
1.PENDING=>默认状态
2.resolved => 成功
3.rejected => 失败
class MyPromise {
constructor(fn){
this.res = null;//存放成功的Value值
this.err = null;//存放失败的Value值
this.status = 'PENDING';//默认是PENGDING状态
try {
fn((res) => {
//调用该方法就是成功
this.status = 'resolved';
this.res = res;
}, (err) => {
//调用该方法就是失败
this.status = 'rejected';
this.err = err
})
} catch (error) {
console.log(error)
}
}
//成功的回调函数
then(onFulfilled, onRejected) {
let self = this;
if (this.status === 'resolved') {
//成功
onFulfilled(self.res);
}
if (this.status === 'rejected') {
//失败
onRejected(self.err);
}
}
}
我们试着使用一下
let p = new MyPromise((resolve,reject)=>{
resolve('1')
})
p.then((res)=>{
//成功的回调
console.log(res,'成功')
},(err)=>{
console.log(err,'失败')
})
//1 成功
现在已经实现了一个基础班的Promise,这里我们只处理了同步操作,但是如果是异步呢?我们试一下!
let p = new MyPromise((resolve,reject)=>{
setTimeout(() => {
resolve('1')
}, 3000);
})
p.then((res)=>{
//成功的回调
console.log(res,'成功')
},(err)=>{
console.log(err,'失败')
})
发现并没有返回任何东西
因为 promise 调用 then 方法时,当前的 promise 并没有成功,一直处于 pending 状态。所以如果当调用 then 方法时,当前状态是 pending,我们需要先将成功和失败的回调分别存放起来,在异步任务被执行时,触发 resolve 或 reject,依次调用成功或失败的回调。
结合这个思路,我们优化一下代码:
//please write a Promise!!!
class MyPromise {
constructor(fn){
this.res = null;
this.err = null;
this.status = 'PENDING';
this.onResolveCallbacks = [];//存放成功的回调
this.onRejectCallbacks = [];//存放失败的回调
try {
fn((res) => {
this.status = 'resolved';
this.res = res;
this.onResolveCallbacks.forEach(fn => fn())
}, (err) => {
this.status = 'rejected';
this.err = err
this.onRejectCallbacks.forEach(fn => fn())
})
} catch (error) {
console.log(error)
}
}
//成功的回调函数
then(onFulfilled, onRejected) {
let self = this;
if (this.status === 'resolved') {
//成功
onFulfilled(self.res);
}
if (this.status === 'rejected') {
//失败
onRejected(self.err);
}
//如果promise的状态是 pending,需要将 onFulfilled 和 onRejected 函数存放起来,等待状态确定后,再依次将对应的函数执行
if (this.status === 'PENDING'){
this.onResolveCallbacks.push(()=>{
onFulfilled(self.res)
})
this.onRejectCallbacks.push(() => {
onFulfilled(self.err)
})
}
}
}
let p = new MyPromise((resolve,reject)=>{
setTimeout(() => {
resolve('1')
}, 3000);
})
p.then((res)=>{
//成功的回调
console.log(res,'成功')
},(err)=>{
console.log(err,'失败')
})