文章一篇,试着写一下Promise。因为不太懂Promise所以试着手写Promise
虽然不太懂内部构造,但也是经常性的去使用,使用的都是一些常见的场景,个别的方法是用不上的,用到的时候再去百度。
开始
先看下原版的类型提示,按照提示写个大概。
\
Promise是个带泛型类,构造函数需要一个executor方法 方法默认会有2个参数,resolve,reject 2个方法,2个方法内各有一个any参数
//构造方法 参数
executor:(resolve:(value:any)=>void,
reject:(reason?:any)=>void)=>void
对比下平时写的结构,可以大概猜出是内部怎么个结构
function test() {
return new Promise((res, rej) => {
setTimeout(() => {
res(123);
}, 10);
});
}
test().then((res) => {
console.log(res);
}).catch((err)=>{
cosole.error(err)
});
那么开始
class MyPromise<T> {
constructor(
exectuor: (
resolve: (value: any) => void,
reject: (reason?: any) => void
) => void
) {
exectuor(this.resolve, this.reject);
}
resolve(value: any): void {}
reject(reason?: any): void {}
}
一个基础架子有了。开始添加内容。写resolve、reject2个方法
resolve(value: any): void { this._value = value; }
reject(reason?: any): void { this._value = reason; }
在promise的规范里,实际使用就是pending=>fulfilled|pending=>rejected,并且不可逆,所以还需要个status
resolve(value: any): void {
if (this.status === "pending") {
this._value = value;
this.status = "fulfilled";
}
}
reject(reason?: any): void {
if (this.status === "pending") {
this._value = reason;
this.status = "rejected";
}
}
下面再开始写then和catch方法,一样的根据常用写法,then会传进来一个方法
test()
.then((res) => {
console.log(res);
})
.catch((err) => {
cosole.error(err);
});
then(fn: (value: any) => void) {
if (this.status === "fulfilled") {
fn(this._value);
}
}
catch(fn: (value: any) => void) {
if (this.status === "rejected") {
fn(this._value);
}
}
感觉差不多了,试一下看看
class MyPromise {
private _value;
private status;
constructor(
exectuor: (
resolve: (value: any) => void,
reject: (reason?: any) => void
) => void
) {
this._value = null;
this.status = "pending";
exectuor(this.resolve, this.reject);
}
resolve(value: any): void {
if (this.status === "pending") {
this._value = value;
this.status = "fulfilled";
}
}
reject(reason?: any): void {
if (this.status === "pending") {
this._value = reason;
this.status = "rejected";
}
}
then(fn: (value: any) => void) {
if (this.status === "fulfilled") {
fn(this._value);
}
}
catch(fn: (value: any) => void) {
if (this.status === "rejected") {
fn(this._value);
}
}
}
function ass() {
return new MyPromise((res, rej) => {
setTimeout(() => {
console.log(123);
res(122);
}, 10);
});
}
ass().then((res) => {
console.log(res);
});
//打印结果
123
结果发现只打印了123,then方法没有执行,测试下
then(fn: (value: any) => void) {
console.log("then");
if (this.status === "fulfilled") {
fn(this._value);
}
}
//打印结果
then
123
看来then方法是执行了的,还是先执行的,是异步的问题。
不能让then 里的参数方法先执行,得拿到值之后再执行。
所以我们把then 里的方法放进resolve里,让异步结果先出来再来执行then里的方法
resolve(value: any): void {
if (this.status === "pending") {
this._value = value;
this.status = "fulfilled";
this.thenFuncs(this._value);
}
}
那么这时候,then 方法就成了收集方法的
resolve(value: any): void {
if (this.status === "pending") {
this._value = value;
this.status = "fulfilled";
this.thenFunc(this._value);
}
}
reject(reason?: any): void {
if (this.status === "pending") {
this._value = reason;
this.status = "rejected";
this.catchFunc(this._value);
}
}
then(fn: (value: any) => void) {
if (this.status === "fulfilled") {
fn(this._value);
}
if (this.status === "pending") {
this.thenFunc = fn;
}
}
catch(fn: (value: any) => void) {
if (this.status === "rejected") {
fn(this._value);
}
if (this.status === "pending") {
this.catchFunc = fn;
}
}
我们再来跑一下,试试
123
嗯?方法还是没有执行?直接打印下看下
resolve(value: any): void {
console.log(this.status);
if (this.status === "pending") {
this._value = value;
this.status = "fulfilled";
console.log(this.status);
this.thenFunc(this._value);
}
}
//
123
undefined
status直接undefind,看来是resolve方法的this对象的问题。直接bind一下,看下完整的
class MyPromise {
private _value;
private status;
private thenFunc;
private catchFunc;
constructor(
exectuor: (
resolve: (value: any) => void,
reject: (reason?: any) => void
) => void
) {
this._value = null;
this.status = "pending";
this.thenFunc = null;
this.catchFunc = null;
exectuor(this.resolve.bind(this), this.reject.bind(this));
}
resolve(value: any): void {
console.log(this.status);
if (this.status === "pending") {
this._value = value;
this.status = "fulfilled";
this.thenFunc(this._value);
}
}
reject(reason?: any): void {
if (this.status === "pending") {
this._value = reason;
this.status = "rejected";
this.catchFunc(this._value);
}
}
then(fn: (value: any) => void) {
if (this.status === "fulfilled") {
fn(this._value);
}
if (this.status === "pending") {
this.thenFunc = fn;
}
}
catch(fn: (value: any) => void) {
if (this.status === "rejected") {
fn(this._value);
}
if (this.status === "pending") {
this.catchFunc = fn;
}
}
}
function ass() {
return new MyPromise((resolve, reject) => {
setTimeout(() => {
console.log(123);
resolve(122);
}, 10);
});
}
ass().then((res) => {
console.log(res);
});
//执行
123
pending
122
ok!初步完成
接下来还有then的调用,待更新