关于前端:手写promise之分步解析

promise是es6推出实用于异步申请的构造函数,帮忙解决回调天堂的问题,以下内容将自定义实现promise,只包含根本应用,所以一些边界状况思考没有在内。
如果对promise用法还不相熟的敌人可移步
Promise的了解与应用(一)
Promise的了解和应用(二)

executor

首先建设promise的根本构造

定义构造函数

promise的executor局部是放到主线程中间接执行的

class icePromise {
    constructor(executor){
        const resolve = () => {
            console.log('resolve被调用')
        }
        const reject = () => {
            console.log('reject被调用')
        }
    }
    executor(resolve, reject)
}

const promise = new icePromise((resolve, reject)=>{
    resolve()
})
定义状态

1、定义常量

const STATUS_PENDING = 'pending'
const STATUS_FULFILLED = 'fulfilled'
const STATUS_REJECTED = 'rejected'

2、通过构造函数创立实例时,就应该须要状态,所以在类中定义

this.status = STATUS_PENDING 

3、resolve和reject办法里通过状态判断
当为pending时,能力执行resolve或者reject办法,执行前先批改状态

then办法

onFulfilled/onRejected中要执行then外面的回调函数,将两个函数绑定到实例的属性上
1、在类中定义一个then办法

then(onFulfilled, onRejected){
    this.onFulfilled = onFulfilled
    this.onRejected = onRejected
}

2、在resolve和reject中别离执行this.onFulfilled和this.onRejected中
此时会报错,因为executor会立即执行,而then外面的函数是微工作,
会在主线程执行实现之后执行

3、resolve和reject中退出 queueMicrotask (微工作)

整体架构的初版就实现了

const STATUS_PENDING = "pending";
const STATUS_FULFILLED = "fulfilled";
const STATUS_REJECTED = "rejected";

class IcePromise {
  constructor(executor) {
    this.status = STATUS_PENDING;
    
    const resolve = (value) => {
      if (this.status === STATUS_PENDING) {
        this.status = STATUS_FULFILLED;
        queueMicrotask(() => {
          this.onFulfilled(value);
        });
      }
    };
    
    const reject = (reason) => {
      if (this.status === STATUS_PENDING) {
        this.status = STATUS_REJECTED;
        queueMicrotask(() => {
          this.onRejected(reason);
        });
      }
    };
    
    executor(resolve, reject);
  }
  
  then(onFulfilled, onRejected) {
    this.onFulfilled = onFulfilled;
    this.onRejected = onRejected;
  }
}

const promise = new IcePromise((resolve, reject) => {
  resolve("resolve");
  reject("reject");
});

promise.then(
  (value) => {
    console.log("success1", value);
  },
  (reason) => {
    console.log("fail1", reason);
  }
);

promise.then(
  (value) => {
    console.log("success2", value);
  },
  (reason) => {
    console.log("fail2", reason);
  }
);

返回两次promise的状态,只执行第一个resolve,then办法中对应执行的胜利或者失败的函数也正确

但存在的问题是,执行两次then办法,只执行了第二个,以下对then办法进行优化。

then

解决屡次调用then办法的问题

1、constructor中定义变量用于收集所有的胜利/失败的回调函数

this.onFulfilledCallbacks = []
this.onRejectedCallbacks = []

2、 在then办法中通过push增加到数组中

this.onFulfilledCallbacks.push()
this.onRejectedCallbacks.push()

3、在resolve和reject中遍历
this.onFulfilledCallbacks和this.onRejectedCallbacks中的办法

此时代码如下

const STATUS_PENDING = "pending";
const STATUS_FULFILLED = "fulfilled";
const STATUS_REJECTED = "rejected";

class IcePromise {
  constructor(executor) {
    this.status = STATUS_PENDING;
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = [];
    
    const resolve = (value) => {
      if (this.status === STATUS_PENDING) {
        queueMicrotask(() => {
          this.onResolvedCallbacks.forEach((fn) => {
            fn(value);
          });
        });
      }
    };
    
    const reject = (reason) => {
      if (this.status === STATUS_PENDING) {
        queueMicrotask(() => {
          this.onRejectedCallbacks.forEach((fn) => {
            fn(reason);
          });
        });
      }
    };
    executor(resolve, reject);
  }
  
  then(onFulfilled, onRejected) {
      this.onResolvedCallbacks.push(onFulfilled);
      this.onRejectedCallbacks.push(onRejected);
  }
}

// 测试代码
const promise = new IcePromise((resolve, reject) => {
  resolve("resolve---");
  reject("----reject");
});
promise.then(
  (value) => {
    console.log("res1", value);
  },
  (reason) => {
    console.log("err1", reason);
  }
)
promise.then(
  (value) => {
    console.log("res2", value);
  },
  (reason) => {
    console.log("err2", reason);
  }
);
// 确定状态后再调用
setTimeout(() => {
  promise.then(
    (res) => {
      console.log("res3", res);
    },
    (err) => {
      console.log("err3", err);
    }
  );
}, 1000);

解决then的屡次调用的问题,但仍有其它的问题,一个是resolve和reject办法同时执行,二是通过定时器提早执行的promise的then办法没有输入响应后果

解决提早调用的问题

1、保留value和reason

this.value = undefined
this.reason = undefined

resolve和reject办法别离给this.value和this.reason赋值

2、then办法中进行状态的判断
当状态为pending时,持续向onFulfilledCallbacks、onRejectedCallbacks数组中增加函数;当状态不为pending时,间接执行onFulfilled或onRejected办法

if (this.status === STATUS_FULFILLED && onFulfilled) {
  onFulfilled(this.value);
}
if (this.status === STATUS_REJECTED && onRejected) {
  onRejected(this.reason);
}

if (this.status === STATUS_PENDING) {
  this.onResolvedCallbacks.push(onFulfilled);
  this.onRejectedCallbacks.push(onRejected);
}

3、pending状态的变动
① queueMicrotask中判断不为pending则return
② 批改pending状态

const STATUS_PENDING = "pending";
const STATUS_FULFILLED = "fulfilled";
const STATUS_REJECTED = "rejected";

class IcePromise {
  constructor(executor) {
    this.status = STATUS_PENDING;
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = [];
    this.value = undefined;
    this.reason = undefined;
    
    const resolve = (value) => {
      if (this.status === STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status !== STATUS_PENDING) return;
          this.status = STATUS_FULFILLED;
          this.value = value;
          this.onResolvedCallbacks.forEach((fn) => {
            fn(this.value);
          });
        });
      }
    };
    
    const reject = (reason) => {
      if (this.status === STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status !== STATUS_PENDING) return;
          this.status = STATUS_REJECTED;
          this.reason = reason;
          this.onRejectedCallbacks.forEach((fn) => {
            fn(this.reason);
          });
        });
      }
    };
    executor(resolve, reject);
  }
  
  then(onFulfilled, onRejected) {
    if (this.status === STATUS_FULFILLED && onFulfilled) {
      onFulfilled(this.value);
    }
    if (this.status === STATUS_REJECTED && onRejected) {
      onRejected(this.reason);
    }
    if (this.status === STATUS_PENDING) {
      this.onResolvedCallbacks.push(onFulfilled);
      this.onRejectedCallbacks.push(onRejected);
    }
  }
}

// 测试代码
const promise = new IcePromise((resolve, reject) => {
  resolve("resolve---");
  reject("----reject");
});

promise.then(
  (value) => {
    console.log("res1", value);
  },
  (reason) => {
    console.log("err1", reason);
  }
)

promise.then(
  (value) => {
    console.log("res2", value);
  },
  (reason) => {
    console.log("err2", reason);
  }
);

// 确定状态后再调用
setTimeout(() => {
  promise.then(
    (res) => {
      console.log("res3", res);
    },
    (err) => {
      console.log("err3", err);
    }
  );
}, 1000);

promise.then(
  (value) => {
    console.log("res4", value);
  },
  (reason) => {
    console.log("err4", reason);
  }
).then(
  (value) => {
    console.log("res5", value);
  },
  (reason) => {
    console.log("err5", reason);
  }
)

解决了resolve和reject屡次调用及计时器提早调用的问题,但此时发现then无奈进行链式调用

解决链式调用的问题

1、then办法里返回一个 new icePromise,将判断逻辑放进去
2、this.onFulfilledCallbacks 和 this.onRejectedCallbacks 传入回调函数,
回调函数返回resolve或者reject函数的执行后果
3、封装工具函数,用于解决try catch

const STATUS_PENDING = "pending";
const STATUS_FULFILLED = "fulfilled";
const STATUS_REJECTED = "rejected";
const respondWithCatchError = (fn, value, resolve, reject) => {
  try {
    const result = fn(value);
    resolve(result);
  } catch (error) {
    reject(error);
  }
};

class IcePromise {
  constructor(executor) {
    this.status = STATUS_PENDING;
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = [];
    this.value = undefined;
    this.reason = undefined;
    
    const resolve = (value) => {
      if (this.status === STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status !== STATUS_PENDING) return;
          this.status = STATUS_FULFILLED;
          this.value = value;
          this.onResolvedCallbacks.forEach((fn) => {
            fn(this.value);
          });
        });
      }
    };
    
    const reject = (reason) => {
      if (this.status === STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status !== STATUS_PENDING) return;
          this.status = STATUS_REJECTED;
          this.reason = reason;
          this.onRejectedCallbacks.forEach((fn) => {
            fn(this.reason);
          });
        });
      }
    };
    executor(resolve, reject);
  }
  
  then(onFulfilled, onRejected) {
    return new Promise((resolve, reject) => {
      if (this.status === STATUS_FULFILLED && onFulfilled) {
        respondWithCatchError(onFulfilled, this.value, resolve, reject);
      }
      if (this.status === STATUS_REJECTED && onRejected) {
        respondWithCatchError(onRejected, this.reason, resolve, reject);
      }
      if (this.status === STATUS_PENDING) {
        this.onResolvedCallbacks.push(() => {
          respondWithCatchError(onFulfilled, this.value, resolve, reject);
        });
        this.onRejectedCallbacks.push(() => {
          respondWithCatchError(onRejected, this.reason, resolve, reject);
        });
      }
    });
  }
}
// 测试代码
const promise = new IcePromise((resolve, reject) => {
  resolve("resolve---");
  reject("----reject");
});
promise
  .then(
    (value) => {
      console.log("res1", value);
    },
    (reason) => {
      console.log("err1", reason);
    }
  )
  .then(
    (value) => {
      console.log("res2", value);
    },
    (reason) => {
      console.log("err2", reason);
    }
  )
  .then(
    (res) => {
      console.log("res3", res);
    },
    (err) => {
      console.log("err3", err);
    }
  );

此时then函数就曾经能够链式调用啦,基本功能曾经实现~

catch

catch函数接管一个失败的回调
1、调用then办法,将onRejected办法加到第二个promise的回调中

catch(onRejected){
    this.then(null, onRejected)
}

2、then办法中对传入的 onRejected进行判断,当没有传递时,就抛出异样

const defaultOnRejected = (reason) => {
  throw reason;
};
onRejected = onRejected || defaultOnRejected;

整体实现如下

const STATUS_PENDING = "pending";
const STATUS_FULFILLED = "fulfilled";
const STATUS_REJECTED = "rejected";

const respondWithCatchError = (fn, value, resolve, reject) => {
  try {
    const result = fn(value);
    resolve(result);
  } catch (error) {
    reject(error);
  }
};

class IcePromise {
  constructor(executor) {
    this.status = STATUS_PENDING;
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = [];
    this.value = undefined;
    this.reason = undefined;

    const resolve = (value) => {
      if (this.status === STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status !== STATUS_PENDING) return;
          this.status = STATUS_FULFILLED;
          this.value = value;
          this.onResolvedCallbacks.forEach((fn) => {
            fn(this.value);
          });
        });
      }
    };

    const reject = (reason) => {
      if (this.status === STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status !== STATUS_PENDING) return;
          this.status = STATUS_REJECTED;
          this.reason = reason;
          this.onRejectedCallbacks.forEach((fn) => {
            fn(this.reason);
          });
        });
      }
    };

    executor(resolve, reject);
  }

  then(onFulfilled, onRejected) {
    const defaultOnFulfilled = (value) => {
      return value;
    };
    const defaultOnRejected = (reason) => {
      throw reason;
    };
    onFulfilled = onFulfilled || defaultOnFulfilled;
    onRejected = onRejected || defaultOnRejected;

    return new Promise((resolve, reject) => {
      if (this.status === STATUS_FULFILLED && onFulfilled) {
        respondWithCatchError(onFulfilled, this.value, resolve, reject);
      }
      if (this.status === STATUS_REJECTED && onRejected) {
        respondWithCatchError(onRejected, this.reason, resolve, reject);
      }

      if (this.status === STATUS_PENDING) {
        this.onResolvedCallbacks.push(() => {
          respondWithCatchError(onFulfilled, this.value, resolve, reject);
        });
        this.onRejectedCallbacks.push(() => {
          respondWithCatchError(onRejected, this.reason, resolve, reject);
        });
      }
    });
  }

  catch(onRejected) {
    this.then(null, onRejected);
  }
}

const promise = new IcePromise((resolve, reject) => {
  reject("----reject");
  resolve("resolve---");
});

// 测试代码
promise
  .then((value) => {
    console.log("res1", value);
  })
  .then((value) => {
    console.log("res2", value);
  })
  .catch((error) => {
    console.log("catch", error);
  });

执行后果如下

finally

finally办法无论执行resolve或者reject的办法后都会执行

finally(onFinally){
    this.then(()=>{
        onFinally()
    }, ()=>{
        onFinally()
    })
}

整体实现如下

const STATUS_PENDING = "pending";
const STATUS_FULFILLED = "fulfilled";
const STATUS_REJECTED = "rejected";

const respondWithCatchError = (fn, value, resolve, reject) => {
  try {
    const result = fn(value);
    resolve(result);
  } catch (error) {
    reject(error);
  }
};

class IcePromise {
  constructor(executor) {
    this.status = STATUS_PENDING;
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = [];
    this.value = undefined;
    this.reason = undefined;
    
    const resolve = (value) => {
      if (this.status === STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status !== STATUS_PENDING) return;
          this.status = STATUS_FULFILLED;
          this.value = value;
          this.onResolvedCallbacks.forEach((fn) => {
            fn(this.value);
          });
        });
      }
    };
    
    const reject = (reason) => {
      if (this.status === STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status !== STATUS_PENDING) return;
          this.status = STATUS_REJECTED;
          this.reason = reason;
          this.onRejectedCallbacks.forEach((fn) => {
            fn(this.reason);
          });
        });
      }
    };
    executor(resolve, reject);
  }
  
  then(onFulfilled, onRejected) {
    const defaultOnFulfilled = (value) => {
      return value;
    };
    const defaultOnRejected = (reason) => {
      throw reason;
    };
    onFulfilled = onFulfilled || defaultOnFulfilled;
    onRejected = onRejected || defaultOnRejected;
    return new Promise((resolve, reject) => {
      if (this.status === STATUS_FULFILLED && onFulfilled) {
        respondWithCatchError(onFulfilled, this.value, resolve, reject);
      }
      if (this.status === STATUS_REJECTED && onRejected) {
        respondWithCatchError(onRejected, this.reason, resolve, reject);
      }
      if (this.status === STATUS_PENDING) {
        this.onResolvedCallbacks.push(() => {
          respondWithCatchError(onFulfilled, this.value, resolve, reject);
        });
        this.onRejectedCallbacks.push(() => {
          respondWithCatchError(onRejected, this.reason, resolve, reject);
        });
      }
    });
  }
  
  catch(onRejected) {
    this.then(null, onRejected);
  }
  
  finally(onFinally) {
    this.then(
      () => {
        onFinally();
      },
      () => {
        onFinally();
      }
    );
  }
}

// 测试代码
const promise = new IcePromise((resolve, reject) => {
  reject("----reject");
});
promise
  .then(
    (value) => {
      console.log("res1", value);
    },
    (reason) => {
      console.log("err1", reason);
    }
  )
  .finally(() => {
    console.log("finally");
  });

resolve/reject

resolve和reject是Promise的类办法,也能够通过调用then办法来实现

static resolve(value){
    return new icePromise((resolve)=>resolve(value))
}

static reject(reason){
    return new icePromise((resolve, reject)=>reject(reason))
}

残缺实现如下

const STATUS_PENDING = "pending";
const STATUS_FULFILLED = "fulfilled";
const STATUS_REJECTED = "rejected";

const respondWithCatchError = (fn, value, resolve, reject) => {
  try {
    const result = fn(value);
    resolve(result);
  } catch (error) {
    reject(error);
  }
};

class IcePromise {
  constructor(executor) {
    this.status = STATUS_PENDING;
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = [];
    this.value = undefined;
    this.reason = undefined;
    
    const resolve = (value) => {
      if (this.status === STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status !== STATUS_PENDING) return;
          this.status = STATUS_FULFILLED;
          this.value = value;
          this.onResolvedCallbacks.forEach((fn) => {
            fn(this.value);
          });
        });
      }
    };
    
    const reject = (reason) => {
      if (this.status === STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status !== STATUS_PENDING) return;
          this.status = STATUS_REJECTED;
          this.reason = reason;
          this.onRejectedCallbacks.forEach((fn) => {
            fn(this.reason);
          });
        });
      }
    };
    executor(resolve, reject);
  }
  
  then(onFulfilled, onRejected) {
    const defaultOnFulfilled = (value) => {
      return value;
    };
    const defaultOnRejected = (reason) => {
      throw reason;
    };
    onFulfilled = onFulfilled || defaultOnFulfilled;
    onRejected = onRejected || defaultOnRejected;
    return new Promise((resolve, reject) => {
      if (this.status === STATUS_FULFILLED && onFulfilled) {
        respondWithCatchError(onFulfilled, this.value, resolve, reject);
      }
      if (this.status === STATUS_REJECTED && onRejected) {
        respondWithCatchError(onRejected, this.reason, resolve, reject);
      }
      if (this.status === STATUS_PENDING) {
        this.onResolvedCallbacks.push(() => {
          respondWithCatchError(onFulfilled, this.value, resolve, reject);
        });
        this.onRejectedCallbacks.push(() => {
          respondWithCatchError(onRejected, this.reason, resolve, reject);
        });
      }
    });
  }
  
  catch(onRejected) {
    this.then(null, onRejected);
  }
  
  finally(onFinally) {
    this.then(
      () => {
        onFinally();
      },
      () => {
        onFinally();
      }
    );
  }
  
  static resolve(value) {
    return new Promise((onResolve) => {
      onResolve(value);
    });
  }
  
  static reject(reason) {
    return new Promise((onResolve, onRejected) => {
      onRejected(reason);
    });
  }
}

// 测试代码
const promise = Promise.reject(1);
promise
  .then(
    (value) => {
      console.log("res1", value);
    },
    (reason) => {
      console.log("err1", reason);
    }
  )

执行后果如下

all/allSettled

all和allSettled办法都是promise的类办法
1、all办法
只有有一个promise执行reject的办法就会执行reject,当所有promise都返回resolve时,才执行resolve办法。
2、allSettled办法
当所有promise都执行实现时,才执行resolve办法,返回所有promise的状态和后果。

static all(promise){
    return new icePromise((resolve, reject)=>{
      const values = []
      promises.forEach(promise => {
        promise.then(res => {
          values.push(res)
          if (values.length === promises.length) {
            resolve(values)
          }
        }, err => {
          reject(err)
        })
      })
    })
    })
}

static allSettled(promise){
    return new icePromise((resolve, reject)=>{
        const values = []
        promise.then(res=>{
            values.push({ status: '', value: '' })
            if(values.length === promise.length){
                resolve(values)
            }
        }, err=>{
            values.push({ status: '', value: '' })
            if(values.length === promise.length){
                resolve(values)
            }
        })
    })
}

残缺实现如下

const STATUS_PENDING = "pending";
const STATUS_FULFILLED = "fulfilled";
const STATUS_REJECTED = "rejected";
const respondWithCatchError = (fn, value, resolve, reject) => {
  try {
    const result = fn(value);
    resolve(result);
  } catch (error) {
    reject(error);
  }
};
class IcePromise {
  constructor(executor) {
    this.status = STATUS_PENDING;
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = [];
    this.value = undefined;
    this.reason = undefined;
    const resolve = (value) => {
      if (this.status === STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status !== STATUS_PENDING) return;
          this.status = STATUS_FULFILLED;
          this.value = value;
          this.onResolvedCallbacks.forEach((fn) => {
            fn(this.value);
          });
        });
      }
    };
    const reject = (reason) => {
      if (this.status === STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status !== STATUS_PENDING) return;
          this.status = STATUS_REJECTED;
          this.reason = reason;
          this.onRejectedCallbacks.forEach((fn) => {
            fn(this.reason);
          });
        });
      }
    };
    executor(resolve, reject);
  }
  then(onFulfilled, onRejected) {
    const defaultOnFulfilled = (value) => {
      return value;
    };
    const defaultOnRejected = (reason) => {
      throw reason;
    };
    onFulfilled = onFulfilled || defaultOnFulfilled;
    onRejected = onRejected || defaultOnRejected;
    return new Promise((resolve, reject) => {
      if (this.status === STATUS_FULFILLED && onFulfilled) {
        respondWithCatchError(onFulfilled, this.value, resolve, reject);
      }
      if (this.status === STATUS_REJECTED && onRejected) {
        respondWithCatchError(onRejected, this.reason, resolve, reject);
      }
      if (this.status === STATUS_PENDING) {
        this.onResolvedCallbacks.push(() => {
          respondWithCatchError(onFulfilled, this.value, resolve, reject);
        });
        this.onRejectedCallbacks.push(() => {
          respondWithCatchError(onRejected, this.reason, resolve, reject);
        });
      }
    });
  }
  catch(onRejected) {
    this.then(null, onRejected);
  }
  finally(onFinally) {
    this.then(
      () => {
        onFinally();
      },
      () => {
        onFinally();
      }
    );
  }
  static resolve(value) {
    return new Promise((onResolve) => {
      onResolve(value);
    });
  }
  static reject(reason) {
    return new Promise((onResolve, onRejected) => {
      onRejected(reason);
    });
  }
  static all(promises) {
    return new Promise((resolve, reject) => {
      const result = [];
      promises.forEach((promise) => {
        promise.then(
          (value) => {
            result.push(value);
            if (result.length === promises.length) {
              resolve(result);
            }
          },
          (reason) => {
            reject(reason);
          }
        );
      });
    });
  }
  static allSettled(promises) {
    return new Promise((resolve, reject) => {
      const result = [];
      promises.forEach((promise) => {
        promise.then(
          (value) => {
            result.push({
              status: STATUS_FULFILLED,
              value,
            });
            if (result.length === promises.length) {
              resolve(result);
            }
          },
          (reason) => {
            result.push({
              status: STATUS_REJECTED,
              reason,
            });
            if (result.length === promises.length) {
              resolve(result);
            }
          }
        );
      });
    });
  }
}

// 测试代码
const promise1 = IcePromise.resolve(1);
const promise2 = new IcePromise((resolve, reject) => {
  setTimeout(() => {
    reject(2);
  });
});
const promise3 = IcePromise.resolve(3);

IcePromise.all([promise1, promise2, promise3]).then(
  (value) => {
    console.log("res1", value);
  },
  (reason) => {
    console.log("err1", reason);
  }
);
IcePromise.allSettled([promise1, promise2, promise3]).then(
  (value) => {
    console.log("res2", value);
  },
  (reason) => {
    console.log("err2", reason);
  }
);

执行后果如下

race/any

race和any都是promise的类办法。
1、race办法
只有有一个promise执行实现,就会返回它所执行的后果

2、any办法
① 有fulfilled状态,会等到这个fullfilled执行实现,执行resolve,后果为value
② 如果所有的Promise都是reject的,那么也会等到所有的Promise都变成rejected状态后报一个AggregateError的谬误。

static race(promises){
    return new icePromise((resolve, reject)=>{
        promises.forEach(promise=>{
            promise.then(resolve, reject)        
        })
    })
}

static any(promises){
    const reasons = []
    return new icePromise((resolve, reject)=>{
        promises.forEach(promise=>{
            promise.then(resolve, err=>{
                reasons.push(err)
                if(reasons.length === promises.length){
                    reject(new AggregateError(reasons))
                }
            })
        })
    })
}

整体实现如下

const STATUS_PENDING = "pending";
const STATUS_FULFILLED = "fulfilled";
const STATUS_REJECTED = "rejected";
const respondWithCatchError = (fn, value, resolve, reject) => {
  try {
    const result = fn(value);
    resolve(result);
  } catch (error) {
    reject(error);
  }
};
class IcePromise {
  constructor(executor) {
    this.status = STATUS_PENDING;
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = [];
    this.value = undefined;
    this.reason = undefined;
    const resolve = (value) => {
      if (this.status === STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status !== STATUS_PENDING) return;
          this.status = STATUS_FULFILLED;
          this.value = value;
          this.onResolvedCallbacks.forEach((fn) => {
            fn(this.value);
          });
        });
      }
    };
    const reject = (reason) => {
      if (this.status === STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status !== STATUS_PENDING) return;
          this.status = STATUS_REJECTED;
          this.reason = reason;
          this.onRejectedCallbacks.forEach((fn) => {
            fn(this.reason);
          });
        });
      }
    };
    executor(resolve, reject);
  }
  then(onFulfilled, onRejected) {
    const defaultOnFulfilled = (value) => {
      return value;
    };
    const defaultOnRejected = (reason) => {
      throw reason;
    };
    onFulfilled = onFulfilled || defaultOnFulfilled;
    onRejected = onRejected || defaultOnRejected;
    return new Promise((resolve, reject) => {
      if (this.status === STATUS_FULFILLED && onFulfilled) {
        respondWithCatchError(onFulfilled, this.value, resolve, reject);
      }
      if (this.status === STATUS_REJECTED && onRejected) {
        respondWithCatchError(onRejected, this.reason, resolve, reject);
      }
      if (this.status === STATUS_PENDING) {
        this.onResolvedCallbacks.push(() => {
          respondWithCatchError(onFulfilled, this.value, resolve, reject);
        });
        this.onRejectedCallbacks.push(() => {
          respondWithCatchError(onRejected, this.reason, resolve, reject);
        });
      }
    });
  }
  catch(onRejected) {
    this.then(null, onRejected);
  }
  finally(onFinally) {
    this.then(
      () => {
        onFinally();
      },
      () => {
        onFinally();
      }
    );
  }
  static resolve(value) {
    return new Promise((onResolve) => {
      onResolve(value);
    });
  }
  static reject(reason) {
    return new Promise((onResolve, onRejected) => {
      onRejected(reason);
    });
  }
  static all(promises) {
    return new Promise((resolve, reject) => {
      const result = [];
      promises.forEach((promise) => {
        promise.then(
          (value) => {
            result.push(value);
            if (result.length === promises.length) {
              resolve(result);
            }
          },
          (reason) => {
            reject(reason);
          }
        );
      });
    });
  }
  static allSettled(promises) {
    return new Promise((resolve, reject) => {
      const result = [];
      promises.forEach((promise) => {
        promise.then(
          (value) => {
            result.push({
              status: STATUS_FULFILLED,
              value,
            });
            if (result.length === promises.length) {
              resolve(result);
            }
          },
          (reason) => {
            result.push({
              status: STATUS_REJECTED,
              reason,
            });
            if (result.length === promises.length) {
              resolve(result);
            }
          }
        );
      });
    });
  }
  static race(promises) {
    return new Promise((resolve, reject) => {
      promises.forEach((promise) => {
        promise.then(resolve, reject);
      });
    });
  }
  static any(promises) {
    return new Promise((resolve, reject) => {
      const reasons = [];
      promises.forEach((promise) => {
        promise.then(resolve, (reason) => {
          reasons.push(reason);
          if (reasons.length === promises.length) {
            reject(new AggregateError(reasons));
          }
        });
      });
    });
  }
}

// 测试代码
const promise1 = new IcePromise((resolve, reject) => {
  setTimeout(() => {
    reject(1);
  });
});
const promise2 = IcePromise.reject(2);
const promise3 = IcePromise.reject(3);
IcePromise.race([promise1, promise2, promise3]).then(
  (value) => {
    console.log("res1", value);
  },
  (reason) => {
    console.log("err1", reason);
  }
);
IcePromise.any([promise1, promise2, promise3]).then(
  (value) => {
    console.log("res1", value);
  },
  (reason) => {
    console.log("err1", reason);
  }
);

以上就是自定义promise的所有代码啦,对于js高级,还有很多须要开发者把握的中央,能够看看我写的其余博文,继续更新中~

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理