试着实现Promise
首先真实的Promise结构如下:
const executor = function (resolve, reject) {
resolve(1);
};
p1 = new Promise(executor);
p1.then((result) => {
console.log(result);
});
可以看到 Promise构造函数接受一个函数executor作为参数,该函数又有两个参数resolve和reject,这两个参数都是函数,当执行到resolve时,会触发then方法,所以该函数需要实现下面几点:
- 构造函数接受一个函数executor,该函数有两个参数,resolve和reject
- 执行该函数executor(resolve,reject)
- 在执行到resolve时,完成状态转化,调用then函数,如果出错则调用catch方法
v1版本
type Executor = (resolve: Resolve, reject: Reject) => void;
type Fn = (params?: any) => void;
type Resolve = (value?: any) => void;
type Reject = (value?: any) => void;
enum State {
Pending = "Pending",
OnFullFilled = "OnFullFilled",
OnRejected = "OnRejected",
}
export class PromiseImpl {
private state: State = State.Pending;
private data = null;
private onFullFilledArr: Fn[] = [];
private onRejectArr: Fn[] = [];
constructor(executor: Executor) {
const resolve = (value: any) => {
this.data = value;
this.state = State.OnFullFilled;
this.onFullFilledArr.forEach((fn) => fn(this.data));
};
const reject = (value: any) => {
this.data = value;
this.state = State.OnRejected;
this.onRejectArr.forEach((fn) => fn(this.data));
};
executor(resolve, reject);
}
then(onFullFilledFn: Fn, onRejectedFn?: Fn) {
if (this.state === State.Pending) {
this.onFullFilledArr.push(onFullFilledFn);
onRejectedFn && this.onRejectArr.push(onRejectedFn);
}
if (this.state === State.OnFullFilled) {
onFullFilledFn(this.data);
}
if (this.state === State.OnRejected) {
onRejectedFn && onRejectedFn(this.data);
}
}
}
未实现链式调用,链式调用依然返回了一个Promise
const p = new PromiseImpl((resolve, reject) => {
setTimeout(() => resolve('resolved first one'), 1000);
});
p.then((res) => {
console.log(res);
return res + ' do some calculation';
}).then(res => {
console.log(res);
});
如何处理链式调用?
首先得返回一个Promise,然后执行onFullFilled,并将返回值放入resolve中
注意,这里的onFullFilledArr 是什么?
这里的onFullFilled应该是一个函数,包裹的是resolve(onFullFilled())
V2
export class PromiseImpl {
private state: State = State.Pending;
private data = null;
private errDate = null;
private onFullFilledArr: Fn[] = [];
private onRejectArr: Fn[] = [];
constructor(executor: Executor) {
const resolve = (value: any) => {
this.data = value;
this.state = State.OnFullFilled;
this.onFullFilledArr.forEach((fn) => fn(this.data));
};
const reject = (value: any) => {
this.data = value;
this.state = State.OnRejected;
this.onRejectArr.forEach((fn) => fn(this.data));
};
executor(resolve, reject);
}
then(onFullFilledFn: Fn, onRejectedFn?: Fn) {
return new PromiseImpl((resolve, reject) => {
if (this.state === State.Pending) {
this.onFullFilledArr.push(() => {
try {
const result = onFullFilledFn(this.data);
resolve(result);
} catch (e) {
this.errDate = e;
reject(e);
}
});
onRejectedFn &&
this.onRejectArr.push(() => {
try {
const result = onRejectedFn(this.data);
reject(result);
} catch (e) {
reject(e);
}
});
}
if (this.state === State.OnFullFilled) {
const result = onFullFilledFn(this.data);
resolve(result);
}
if (this.state === State.OnRejected) {
onRejectedFn && onRejectedFn(this.data);
}
});
}
}
是否还有问题?
思考then 里面也可以返回Promise
const p1 = new Promise((resolve, reject) => {
setTimeout(() => resolve('resolved first one'), 1000);
})
p1.then((res) => {
console.log(res);
return new Promise(resolve => {
setTimeout(() => resolve('resolved second one'), 1000);
});
}).then(res => {
console.log(res);
});
一共产生了三个Promise
- p1
- 链式调用里then产生了一个
- then的onFullFilled里面返回了一个Promise
判断如果onFullFilled如果是Promise类型,则调用第二个的then方法
Promise的解决顺序 1-->3--->2
export class PromiseImpl {
private state: State = State.Pending;
private data = null;
private errDate = null;
private onFullFilledArr: Fn[] = [];
private onRejectArr: Fn[] = [];
constructor(executor: Executor) {
const resolve = (value: any) => {
this.data = value;
this.state = State.OnFullFilled;
this.onFullFilledArr.forEach((fn) => fn(this.data));
};
const reject = (value: any) => {
this.data = value;
this.state = State.OnRejected;
this.onRejectArr.forEach((fn) => fn(this.data));
};
executor(resolve, reject);
}
then(onFullFilledFn: Fn, onRejectedFn?: Fn) {
return new PromiseImpl((resolve, reject) => {
if (this.state === State.Pending) {
this.onFullFilledArr.push(() => {
try {
const fulfilledFromLastPromise = onFullFilledFn(this.data);
if (fulfilledFromLastPromise instanceof PromiseImpl) {
// 这个函数onFullFilledArr里的
fulfilledFromLastPromise.then(resolve, reject);
} else {
resolve(fulfilledFromLastPromise);
}
} catch (e) {
this.errDate = e;
reject(e);
}
});
onRejectedFn &&
this.onRejectArr.push(() => {
try {
const result = onRejectedFn(this.data);
reject(result);
} catch (e) {
reject(e);
}
});
}
if (this.state === State.OnFullFilled) {
const result = onFullFilledFn(this.data);
resolve(result);
}
if (this.state === State.OnRejected) {
onRejectedFn && onRejectedFn(this.data);
}
});
}
}
注意这里 fulfilledFromLastPromise.then(resolve, reject);
这里是将 该函数push 进了onFullFilledArr,然后再resolve的时候调用