1. Promise源码分析
1. Promise三种状态
pending(进行中)、fulfilled(已成功)、rejected(已失败)
2. new Promise()对象参数
是一个回调函数, 该回调函数接受两个参数,分别是成功时的回调resolve和失败时的回
调reject;
- resolve的参数除了正常值以外, 还可能是一个Promise对象的实例;
- reject的参数通常是一个Error对象的实例;
3. then()方法
返回一个新的Promise实例.
接收两个参数:
- onResolved(fulfilled状态的回调);
- onRejected(rejected状态的回调,该参数可选)
4.catch()方法
返回一个新的promise对象
5. finally()方法
finally方法不管Promise状态如何都会执行,该方法的回调函数不接受任何参数
6. Promise.all()方法
- 将多个Promise实例,包装成一个新的Promise实例
- 入参: 由Promise对象组
成的数组作为参数(Promise.all()方法的参数可以不是数组,但必须具有Iterator接口,且返回的每个成员都是
Promise实例) - 注意: 参数中只要有一个实例触发catch方法,都会触发Promise.all()方法返回的新的实例的catch方法
7. Promise.race()方法
- 入参: 参数与Promise.all方法一样
- 执行说明: 参数中的实例只要有一个率先改变状态就会将该实例的状态传给Promise.race()方法,并将返回值作为Promise.race()方法产生的Promise实例的返回值
8. Promise.resolve()方法
将现有对象转为Promise对象
- 如果该方法的参数为一个Promise对象,Promise.resolve()将不做任何处理;
- 如果参数thenable对象(即具有then方法),Promise.resolve()将该对象转为Promise对象并立即执行then方法;
- 如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的Promise对象,状态为fulfilled,其参数将会作为then方法中onResolved回调函数的参数.
- 如果Promise.resolve方法不带参数,会直接返回一个fulfilled状态的 Promise 对象。
- 需要注意的是,立即resolve()的 Promise 对象,是在本轮“事件循环”(event loop)的结束时执行,而不是在下一轮“事
件循环”的开始时。
9. Promise.reject()方法
同样返回一个新的Promise对象,状态为rejected,无论传入任何参数都将作为reject()的参数
2. Promise代码实现
// 初始状态const PENDING = "pending";// 完成状态const FULFILLED = "fulfilled";// 失败状态const REJECTED = "rejected";// 异步执行方法封装function asyncExecFun(fn) {setTimeout(() => fn(), 0);}// 执行promise resolve功能function resolvePromise(promise, res, resolve, reject) {// 返回同一个promiseif (promise === res) {reject(new TypeError("Chaining cycle detected for promise #<MyPromise>"));return;}// promise结果if (res instanceof MyPromise) {res.then(resolve, reject);} else {// 非promise结果resolve(res);}}class MyPromise {status = PENDING;value = undefined;reason = undefined;successCallbacks = [];failCallbacks = [];constructor(exector) {// 立即执行传入参数// 参数直接写为 this.resolve 会导致函数内 this指向会发生改变// 异步执行状态变更// 捕获执行器的异常try {exector((value) => asyncExecFun(() => this.resolve(value)),(reason) => asyncExecFun(() => this.reject(reason)));} catch (e) {this.reject(e)}}resolve(value) {// 如果状态已经变更则直接返回if (this.status !== PENDING) return;this.value = value;this.status = FULFILLED;// 执行所有成功回调while (this.successCallbacks.length) this.successCallbacks.shift()();}reject(reason) {// 如果状态已经变更则直接返回if (this.status !== PENDING) return;this.reason = reason;this.status = REJECTED;if(!this.failCallbacks.length){throw '(in MyPromise)'}// 执行所有失败回调while (this.failCallbacks.length) this.failCallbacks.shift()();}then(successCallback, failCallback) {// 成功函数处理 忽略函数之外的其他值successCallback =typeof successCallback == "function" ? successCallback : (v) => v;// 失败函数处理 忽略函数之外的其他值 抛出异常 实现catch冒泡的关键failCallback =typeof failCallback == "function"? failCallback: (reason) => {throw reason;};let promise = new MyPromise((resolve, reject) => {// 统一异常处理逻辑const execFun = (fn, val) => {try {let res = fn(val);resolvePromise(promise, res, resolve, reject);} catch (e) {reject(e);}};// 执行成功回调const execSuccessCallback = () => execFun(successCallback, this.value);// 执行失败回调const execFailCallback = () => execFun(failCallback, this.reason);// 同步将对应成功或者失败回调事件加入对应回调队列if (this.status === PENDING) {// 将成功回调加入队列this.successCallbacks.push(execSuccessCallback);// 讲失败回调加入队列this.failCallbacks.push(execFailCallback);return;}// 延迟执行 可以将函数执行结果和当前then 返回的promise 进行比较asyncExecFun(() => {// 如果已经 fulfilled 可直接调用成功回调方法if (this.status === FULFILLED) {execSuccessCallback();// 如果已经 rejected 可直接调用失败回调方法} else if (this.status === REJECTED) {execFailCallback();}});});return promise;}catch(failCallback) {return this.then(undefined, failCallback);}finally(callback) {return this.then(// 穿透正常值(value) => MyPromise.resolve(callback()).then(() => value),(reason) =>MyPromise.resolve(callback()).then(() => {// 穿透异常信息throw reason;}));}static resolve(value) {// 如果是MyPromise 实例 则直接返回if (value instanceof MyPromise) return value;// 如果是MyPromise 实例 否则返回一个 MyPromise实例return new MyPromise((resolve) => resolve(value));}static reject(reason) {// 如果是MyPromise 实例 则直接返回if (reason instanceof MyPromise) return reason;// 如果是MyPromise 实例 否则返回一个 MyPromise实例return new MyPromise((resolve, reject) => reject(reason));}// all方法static all(array) {// 存储结果let result = [];// 存储数组长度let len = array.length;// 创建返回MyPromiselet promise = new MyPromise((resolve, reject) => {// 定义当前MyPromise的索引let index = 0;// 添加数据的公用方法function addData(key, data) {// 赋值result[key] = data;// 索引递增index++;// 全部执行完则resolveif (index == len) {resolve(result);}}// 按顺序变量数组for (let i = 0; i < len; i++) {let curr = array[i];// 如果是MyPromise则 按其规则处理if (curr instanceof MyPromise) {curr.then((value) => addData(i, value), reject);} else {// 非MyPromise直接赋值addData(i, curr);}}});// 返回新的MyPromise实例return promise;}// 只要有一个成功或者失败就返回static race(array) {let promise = new MyPromise((resolve, reject) => {for (let i = 0; i < array.length; i++) {let curr = array[i];// MyPromise实例 结果处理if (curr instanceof MyPromise) {curr.then(resolve, reject);} else {// 非MyPromise实例处理resolve(curr);}}});return promise;}}module.exports = MyPromise;
