手写Promise,从入门到毕业
根据PromiseA+规范实现此代码,注意:Promise的异步任务是浏览器的quenemicrotask API实现的,此代码并没使用此API,代码只实现基本功能;渡一教育yyds!!!
1.手写promise构造器
enum Status{
PENDING = "pending",
FULFILLED = "fulfilled",
REJECTED = "rejected"
}
class IPromise{
private _status:string = Status.PENDING;
private _result:any = undefined;
constructor(executer:Function){
const resolve:Function = (data)=>{
this.changeStatus(Status.FULFILLED,data)
};
const reject:Function = (reason)=>{
this.changeStatus(Status.REJECTED,reason)
};
//只能捕获同步error
try {
executer(resolve,reject);
} catch (error) {
reject(error)
}
}
private changeStatus(status:string,result:any){
if(this._status !== Status.PENDING) return;
this._status = status;
this._result = result;
}
}
(1)Status 是一个枚举类型,用于表示 Promise 的状态。该枚举类型定义了三个常量:PENDING、FULFILLED、REJECTED,分别表示 Promise 的三种状态。
(2)IPromise 类是 Promise 实现的核心部分。在构造函数中,它接收一个执行器(executor)函数作为参数,并将其保存在内部变量中。该执行器函数包含两个回调函数 resolve 和 reject,分别用于异步操作成功和失败时的处理。当 Promise 被创建时,执行器函数会立即执行。
(3)在 IPromise 类中,定义了两个私有变量 _status 和 _result,分别用于保存 Promise 的状态和结果。初始状态为 PENDING,结果为 undefined。在实现过程中,需要注意保证 Promise 状态不可逆。
(4)changeStatus 方法是一个私有方法,用于修改 Promise 的状态和结果。如果 Promise 已经处于非 PENDING 状态,就不再进行状态的更新。
(5)在 executer 函数中,只能捕获同步错误。如果发生异步错误,需要在回调函数中进行错误处理,否则会导致程序崩溃。
2.Promise核心then方法
enum Status {
PENDING = "pending",
FULFILLED = "fulfilled",
REJECTED = "rejected"
}
class IPromise {
private _status: string = Status.PENDING;
private _result: any = undefined;
private Handlers = [];
constructor(executer: Function) {
const resolve: Function = (data) => {
this.changeStatus(Status.FULFILLED, data)
};
const reject: Function = (reason) => {
this.changeStatus(Status.REJECTED, reason)
};
//只能捕获同步error
try {
executer(resolve, reject);
} catch (error) {
reject(error)
}
}
private changeStatus(status: string, result: any) {
if (this._status !== Status.PENDING) return;
this._status = status;
this._result = result;
this.run();
}
//A+规范方法
then(onFulfilled?, onReject?) {
return new IPromise((resolve, reject) => {
this.Handlers.push({
onFulfilled,
onReject,
resolve,
reject
})
this.run()
})
}
private runOne(callback, resolve, reject) {
//将任务加到微队列
this.runMicroTask(() => {
if (typeof callback !== "function") {
const setted = this._status === Status.FULFILLED ? resolve : reject;
setted(this._result);
return;
}
try {
const data = callback(this._result);
if (this.isPromise(data)) {
data.then(resolve, reject);
} else {
resolve(data);
}
} catch (error) {
reject(error);
}
})
}
private run() {
if (this._status === Status.PENDING) return;
while (this.Handlers.length) {
const { onFulfilled, onReject, resolve, reject } = this.Handlers.shift();
if (this._status === Status.FULFILLED) {
this.runOne(onFulfilled, resolve, reject);
} else {
this.runOne(onReject, resolve, reject);
}
}
}
private isPromise(val) {
if (val !== null && typeof val === "function" || "object") {
return typeof val.then === "function";
}
return false;
}
private runMicroTask(fn) {
//此处可以使用前文提到的API
if (typeof process === "object" && typeof process.nextTick === "function") {
process.nextTick(fn);
} else if (typeof queueMicrotask === "function") {
queueMicrotask(fn)
} else {
setTimeout(fn, 0)
}
}
}
3.es6定义方法,具体函数实现方法需要查看mdn官方文档
//es6规定promise方法
catch(onReject) {
return this.then(undefined, onReject)
}
finlly(onFinally) {
return this.then((data) => {
onFinally();
return data;
}, (err) => {
onFinally();
throw err;
})
}
static resolve(val) {
if (val instanceof IPromise) return val;
let _resolve, _reject;
const p = new IPromise((resolve,reject)=>{
_resolve = resolve;
_reject = reject
})
if(p.isPromise(val)){
val.then(_resolve,_reject)
}else{
_resolve(val);
}
return p;
}
static reject(reason) {
return new IPromise((resolve,reject)=>{
reject(reason);
})
}