// 记录Promise的三种状态 const PENDING = 'pending'; const FULFILLED = 'fulfilled'; const REJECTED = 'rejected'; /** * 运行一个微队列任务 * 把传递的函数放到微队列中 * @param {Function} callback */ function runMicroTask(callback) { // 判断node环境 // 为了避免「变量未定义」的错误,这里最好加上前缀globalThis // globalThis是一个关键字,指代全局对象,浏览器环境为window,node环境为global if (globalThis.process && globalThis.process.nextTick) { process.nextTick(callback); } else if (globalThis.MutationObserver) { const p = document.createElement('p'); const observer = new MutationObserver(callback); observer.observe(p, { childList: true, // 观察该元素内部的变化 }); p.innerHTML = '1'; } else { setTimeout(callback, 0); } } /** * 判断一个数据是否是Promise对象 * @param {any} obj * @returns */ function isPromise(obj) { return !!(obj && typeof obj === 'object' && typeof obj.then === 'function'); } class MyPromise { /** * 创建一个Promise * @param {Function} executor 任务执行器,立即执行 */ constructor(executor) { this._state = PENDING; // 状态 this._value = undefined; // 数据 this._handlers = []; // 处理函数形成的队列 try { executor(this._resolve.bind(this), this._reject.bind(this)); } catch (error) { this._reject(error); console.error(error); } } /** * 向处理队列中添加一个函数 * @param {Function} executor 添加的函数 * @param {String} state 该函数什么状态下执行 * @param {Function} resolve 让then函数返回的Promise成功 * @param {Function} reject 让then函数返回的Promise失败 */ _pushHandler(executor, state, resolve, reject) { this._handlers.push({ executor, state, resolve, reject, }); } /** * 根据实际情况,执行队列 */ _runHandlers() { if (this._state === PENDING) { // 目前任务仍在挂起 return; } while (this._handlers[0]) { const handler = this._handlers[0]; this._runOneHandler(handler); this._handlers.shift(); } } /** * 处理一个handler * @param {Object} handler */ _runOneHandler({ executor, state, resolve, reject }) { runMicroTask(() => { if (this._state !== state) { // 状态不一致,不处理 return; } if (typeof executor !== 'function') { // 传递后续处理并非一个函数 this._state === FULFILLED ? resolve(this._value) : reject(this._value); return; } try { const result = executor(this._value); if (isPromise(result)) { result.then(resolve, reject); } else { resolve(result); } } catch (error) { reject(error); console.error(error); } }); } /** * Promise A+规范的then * @param {Function} onFulfilled * @param {Function} onRejected */ then(onFulfilled, onRejected) { return new MyPromise((resolve, reject) => { this._pushHandler(onFulfilled, FULFILLED, resolve, reject); this._pushHandler(onRejected, REJECTED, resolve, reject); this._runHandlers(); // 执行队列 }); } /** * 仅处理失败的场景 * @param {Function} onRejected */ catch(onRejected) { return this.then(null, onRejected); } /** * 无论成功还是失败都会执行回调 * @param {Function} onSettled */ finally(onSettled) { return this.then( (data) => { onSettled(); return data; }, (reason) => { onSettled(); throw reason; } ); } /** * 更改任务状态 * @param {String} newState 新状态 * @param {any} value 相关数据 */ _changeState(newState, value) { if (this._state !== PENDING) { // 目前状态已经更改 return; } // 下面这个判断是为了处理value为Promise的情况 // 这一段代码课程中没有涉及,特此注释说明 if (isPromise(value)) { value.then(this._resolve.bind(this), this._reject.bind(this)); return; } this._state = newState; this._value = value; this._runHandlers(); // 状态变化,执行队列 } /** * 标记当前任务完成 * @param {any} data 任务完成的相关数据 */ _resolve(data) { this._changeState(FULFILLED, data); } /** * 标记当前任务失败 * @param {any} reason 任务失败的相关数据 */ _reject(reason) { this._changeState(REJECTED, reason); } /** * 返回一个已完成的Promise * 特殊情况: * 1. 传递的data本身就是ES6的Promise对象 * 2. 传递的data是PromiseLike(Promise A+),返回新的Promise,状态和其保持一致即可 * @param {any} data */ static resolve(data) { if (data instanceof MyPromise) { return data; } return new MyPromise((resolve, reject) => { if (isPromise(data)) { data.then(resolve, reject); } else { resolve(data); } }); } /** * 得到一个被拒绝的Promise * @param {any}} reason */ static reject(reason) { return new MyPromise((resolve, reject) => { reject(reason); }); } /** * 得到一个新的Promise * 该Promise的状态取决于proms的执行 * proms是一个迭代器,包含多个Promise * 全部Promise成功,则返回的Promise成功,数据为所有Promise成功的数据,并且顺序是按照传入的顺序排列 * 只要有一个Promise失败,则返回的Promise失败,原因是第一个失败的Promise的原因 * @param {iterator} proms */ static all(proms) { return new MyPromise((resolve, reject) => { try { const results = []; let count = 0; // Promise的总数 let fulfilledCount = 0; // 已完成的数量 for (const p of proms) { let i = count; count++; MyPromise.resolve(p).then((data) => { fulfilledCount++; results[i] = data; if (fulfilledCount === count) { // 当前是最后一个Promise完成了 resolve(results); } }, reject); } if (count === 0) { resolve(results); } } catch (error) { reject(error); console.error(error); } }); } /** * 等待所有的Promise有结果之后 * 该方法返回的Promise完成 * 并且按照顺序将所有结果汇总 * @param {iterator} proms */ static allSettled(proms) { const ps = []; for (const p of proms) { ps.push( MyPromise.resolve(p).then( (value) => ({ status: FULFILLED, value, }), (reason) => ({ status: REJECTED, reason, }) ) ); } return MyPromise.all(ps); } /** * 返回的Promise与第一个有结果的一致 * @param {iterator} proms */ static race(proms) { return new MyPromise((resolve, reject) => { for (const p of proms) { MyPromise.resolve(p).then(resolve, reject); } }); } }