在模拟实现promise之前,先要熟悉了解promise的基本功能和语法。首先promise传入的参数是一个立即执行函数,立即执行函数内又有两个函数,resolve与reject,分别对应函数成功执行的回调和失败情况的回调。两个函数都有一个参数,分别为value与reason。promise特点是状态一旦改变,就无法转变。
promise支持链式调用,通过then方法,原理是在then方法内部new 一个新的promise实例,返回这个实例的处理结果。catch与finally实际上是对then方法的封装。
class Promise(){
constructor(excutor){
this.state = "pending"; //状态变量
this.value = undefined;
this.reason = undefined;
this.onResolvedFn = []; //promise内异步改变state状态时存储待执行resolve函数的数组
this.onRejectedFn = [];
let resolve = value => {
if(this.state === "pending"){
this.state = "fulfilled";
this.value = value;
this.onResolvedFn.forEach(fn => fn());
}
let reject= reason => {
if(this.state === "pending"){
this.state = "rejected";
this.reason = reason ;
this.onRejectedFn .forEach(fn => fn());
}
try{
excutor(resolve,reject)
}catch(err){
reject(err)
}
}
}
//then方法接受两个函数,分别是fulfilled状态执行的,和rejected状态执行,还要返回一个新的promise
then(onFulfilled,onRejected){
let p2 = new Promise(resolve,reject){
if(this.state==="fulfilled"){
setTimeout(() => {
let x = onFulfilled(this.value);
resolvePromise(p2,x,resolve,reject);
})
}
if(this.state==="rejected"){
setTimeout(() => {
let x = onRejected(this.reason);
resolvePromise(p2,x,resolve,reject);
})
}
if(this.state === "pending"){
this.onResolvedFn.push(() => {
setTimeout(() => {
let x = onFulfilled(this.value);
resolvePromise(p2,x,resolve,reject);
})
})
this.onRejectedFn.push(() => {
setTimeout(() => {
let x = onRejected(this.reason);
resolvePromise(p2,x,resolve,reject);
})
})
}
return p2 ;
}
}
}
function resolvePromise(p , x , resolve , reject){
if(p===x){
return reject(new TypeError("Chaning cycle detected for promise"));
}
let called;
if(x !== null && (typeof x === "object" || typeof x === "function")){
try {
let then = x.then;
if(typeof then == "function"){
then.call(x, y =>{
if(called) return;
called = true;
resolvePromise(p,y,resolve,reject)
} , err => {
if(called) return;
called = true;
reject(err);
})
}else{
resolve(x);
}
}catch(e){
if(called) return;
called = true;
reject(e);
}
}else{
resolve(x);
}
}
//reolve方法
Promise.resolve = val => {
return new Promise((resolve,reject) => resolve(val))
}
//reject方法
Promise.reject= reason=> {
return new Promise((resolve,reject) => reject(reason))
}