手写 promise 之路
- 先看一下我们正常的使用场景
var test = new TestPromise((res,rej)=> {
setTimeout(() => {
res(99999)
},1000)
})
test.then((a) => {
console.log(1111,a)
})
- 这是按照使用场景的第一次尝试的代码
class TestPromise {
constructor(callback) {
this.status = 'pending'
callback(this.resolve, this.reject)
}
resolve = (data) => {
if(this.status == 'pending') {
this.status = 'resolve'
console.log('进入resolve')
return data
}
}
reject = (data) => {
if(this.status == 'pending') {
this.status = 'reject'
console.log('进入reject')
return data
}
}
then = (resolveResult) => {
console.log(this.status)
if(this.status == 'resolve') {
resolveResult()
}
}
}
- 运行一下看一下打印结果
pending
进入resolve
- 此时发现会先执行我们的 then 方法,然后在执行的 resolve 方法这和我们预期的完全不一样, 因为按照预期应该是等 resolve 后在执行 then 方法,这个时候才想到是缺了发布订阅的通知,所以下面的步骤应该是能有一个发布订阅的消息通知。网上关于发布订阅这一块已经说的很多了,这里就不缀余了。代码如下:
/**
* 事件监听
*/
let keyCount = 1;
export default class Monitor {
list: any = {};
// 注册
on = (fun: any = () => {}) => {
const key = `key-${keyCount++}-${+new Date()}`;
this.list[key] = fun;
return {
key,
off: () => {
this.off(key);
}
};
};
// 注册一次执行后关闭
once = (fn: any = () => {}) => {
const _id = this.on((res: any) => {
_id.off();
return fn(res);
});
return _id;
};
// // 删除
off = (key: string | number) => {
delete this.list[key];
return true;
};
go = (...res: any) => {
const resList = [];
for (const key in this.list) {
try {
resList.push(this.list[key](...res));
} catch (e) {
resList.push(new Error(e));
}
}
return resList;
};
// // 删除所有事件注册
offAll = () => {
this.list = {};
return true;
};
}
- 加上两个数组用来存储事件(传统的是用对象来当事件中心,但是我们不需要定义事件的名称,所以就直接用两个数组来储存就行了,因为我们的事件就只有两个)
class TestPromise {
constructor(callback) {
this.status = "pending";
this.resolveEventArr = [];
this.rejectEventArr = [];
callback(this.resolve, this.reject);
}
resolve = (data) => {
if (this.status == "pending") {
this.status = "resolve";
this.resolveEventArr.forEach((item) => item(data));
console.log("进入resolve");
}
};
reject = (data) => {
if (this.status == "pending") {
this.status = "reject";
this.rejectEventArr.forEach((item) => item(data));
console.log("进入reject");
}
};
then = (resolveEvent, rejectEvent) => {
console.log(this.status);
if (this.status == "pending") {
this.resolveEventArr.push(resolveEvent);
this.rejectEventArr.push(rejectEvent);
}
};
}
var test = new TestPromise((res, rej) => {
setTimeout(() => {
res(99999);
}, 1000);
});
test.then((a) => {
console.log(1111, a);
});
网友评论