2024-02-19
JavaScript
00
请注意,本文编写于 684 天前,最后修改于 661 天前,其中某些信息可能已经过时。

目录

构造函数
实现resolve和reject
实现then
promises-aplus-tests测试用例

本文带大家手写promise,和官方的promise保持一致可以互操作,关于promise的基础知识这里就不再过多赘述了,网上有很多资料,如果有不懂的大家可以上网查阅其它资料 代码地址gitee

构造函数

js
class MyPromise { constructor(executor) { // 实例化Promise时必须传入一个执行器函数,该函数接收两个参数 resolve和reject用来改变promise的状态 executor(this.resolve.bind(this),this.reject.bind(this)) } resolve () { } reject () { } }

实现resolve和reject

js
class MyPromise { // 私有属性,防止外部修改该属性的值 #PromiseState = PENDING; #PromiseResult = undefined; #onFulfilledCallbacks = []; // 保存成功时的回调函数 #onRejectedCallbacks = []; // 保存失败时的回调函数 constructor(executor) { // 实例化Promise时必须传入一个执行器函数,该函数接收两个参数 resolve和reject用来改变promise的状态 executor(this.resolve.bind(this),this.reject.bind(this)) } resolve (result) { if (this.#PromiseState !== PENDING) return; this.#PromiseState = FULFILLED; this.#PromiseResult = result; this.#onFulfilledCallbacks.forEach(callback => { callback(result) }) } reject (reason) { if (this.#PromiseState !== PENDING) return; this.#PromiseState = REJECTED; this.#PromiseResult = reason; this.#onRejectedCallbacks.forEach(callback => { callback(reason) }) } }

实现then

js
const PENDING = 'PENDING'; const FULFILLED = 'FULFILLED'; const REJECTED = 'REJECTED'; class MyPromise { // 私有属性,防止外部修改该属性的值 #PromiseState = PENDING; #PromiseResult = undefined; #onFulfilledCallbacks = []; // 保存成功时的回调函数 #onRejectedCallbacks = []; // 保存失败时的回调函数 constructor(executor) { try { // 实例化Promise时必须传入一个执行器函数,该函数接收两个参数 resolve和reject用来改变promise的状态 executor(this.resolve.bind(this), this.reject.bind(this)) } catch (error) { this.reject(error); } } resolve (result) { if (this.#PromiseState !== PENDING) return; this.#PromiseState = FULFILLED; this.#PromiseResult = result; this.#onFulfilledCallbacks.forEach(callback => { callback(result) }) } reject (reason) { if (this.#PromiseState !== PENDING) return; this.#PromiseState = REJECTED; this.#PromiseResult = reason; this.#onRejectedCallbacks.forEach(callback => { callback(reason) }) } // 链式调用的then方法 // 该方法接收两个参数 onFulfilled 和 onRejected,它们都是可选的,分别表示当Promise状态变为fulfilled和rejected时的回调函数 then (onFulfilled, onRejected) { let promise2 = new MyPromise((resolve, reject) => { if (this.#PromiseState === FULFILLED) { runMicroTask(() => { try { if (typeof onFulfilled !== 'function') { resolve(this.#PromiseResult); } else { let x = onFulfilled(this.#PromiseResult); resolvePromise(promise2, x, resolve, reject); } } catch (e) { reject(e); } }) } else if (this.#PromiseState === REJECTED) { runMicroTask(() => { try { if (typeof onRejected !== 'function') { reject(this.#PromiseResult); } else { let x = onRejected(this.#PromiseResult); resolvePromise(promise2, x, resolve, reject); } } catch (e) { reject(e); } }) } else { this.#onFulfilledCallbacks.push(() => { runMicroTask(() => { try { if (typeof onFulfilled !== 'function') { resolve(this.#PromiseResult); } else { let x = onFulfilled(this.#PromiseResult); resolvePromise(promise2, x, resolve, reject); } } catch (e) { reject(e); } }) }); this.#onRejectedCallbacks.push(() => { runMicroTask(() => { try { if (typeof onRejected !== 'function') { reject(this.#PromiseResult); } else { let x = onRejected(this.#PromiseResult); resolvePromise(promise2, x, resolve, reject); } } catch (e) { reject(e); } }) }); } }) return promise2 } } runMicroTask = (task) => { //queueMicrotask(task); if (typeof process !== 'undefined' && typeof process.nextTick === 'function') { // node环境 return process.nextTick(task); } else if (typeof MutationObserver === "function") { const ob = new MutationObserver(task); const textNode = document.createTextNode('1') ob.observe(textNode, { characterData: true }) textNode.data = '2' } else { setTimeout(task, 0); } } resolvePromise = (promise2, x, resolve, reject) => { // 2.3.1规范 如果 promise 和 x 指向同一对象,以 TypeError 为据因拒绝执行 promise if (x === promise2) { throw new TypeError('Chaining cycle detected for promise'); } if (x instanceof MyPromise) { /** * 2.3.2 如果 x 为 Promise ,则使 promise2 接受 x 的状态 * 也就是继续执行x,如果执行的时候拿到一个y,还要继续解析y */ x.then(y => { resolvePromise(promise2, y, resolve, reject); }, reject) } else if (x !== null && ((typeof x === 'object' || (typeof x === 'function')))) { // 2.3.3 如果 x 为对象或函数 try { // 2.3.3.1 把 x.then 赋值给 then var then = x.then; } catch (e) { // 2.3.3.2 如果取 x.then 的值时抛出错误 e ,则以 e 为据因拒绝 promise return reject(e); } /** * 2.3.3.3 * 如果 then 是函数,将 x 作为函数的作用域 this 调用之。 * 传递两个回调函数作为参数, * 第一个参数叫做 `resolvePromise` ,第二个参数叫做 `rejectPromise` */ if (typeof then === 'function') { // 2.3.3.3.3 如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用 let called = false; // 避免多次调用 try { then.call(x, // 2.3.3.3.1 如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y) y => { if (called) return; called = true; resolvePromise(promise2, y, resolve, reject); }, // 2.3.3.3.2 如果 rejectPromise 以据因 r 为参数被调用,则以据因 r 拒绝 promise r => { if (called) return; called = true; reject(r); } ) } catch (error) { /** * 2.3.3.3.4 如果调用 then 方法抛出了异常 e * 2.3.3.3.4.1 如果 resolvePromise 或 rejectPromise 已经被调用,则忽略之 */ if (called) return; called = true; // 2.3.3.3.4.2 否则以 e 为据因拒绝 promise reject(error); } } else { // 2.3.3.4 如果 then 不是函数,以 x 为参数执行 promise resolve(x); } } else { // 2.3.4 如果 x 不为对象或者函数,以 x 为参数执行 promise return resolve(x); } }; isPromiseLike = (value) => { return value && typeof value.then === 'function'; }

promises-aplus-tests测试用例

image.png

如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:繁星

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!