深入浅出手写JavaScript Promise

需积分: 9 0 下载量 200 浏览量 更新于2024-12-13 收藏 1KB ZIP 举报
资源摘要信息: "js代码-手写Promise" 在前端开发领域,Promise是处理异步操作的一种强大工具,它让异步代码的组织和错误处理更加清晰和优雅。Promise 的核心思想是通过一个代表了异步操作最终完成或失败的对象,将异步操作的未来完成或失败状态与对应的处理方法关联起来。在 JavaScript 中,Promise 是一个内置对象,但了解如何从头开始手写一个 Promise 对象,对于深入理解其工作原理和设计模式具有重要意义。 Promise对象有三种状态:pending(等待中)、fulfilled(已成功)和rejected(已失败)。一个Promise从pending开始,然后根据异步操作的结果,要么转换为fulfilled,要么转换为rejected。 以下是一个手写Promise的示例代码,包含了Promise构造函数、then方法和catch方法的核心实现。 ```javascript class MyPromise { // Promise构造函数接受一个执行函数,该执行函数接受两个参数,resolve和reject constructor(executor) { this.state = 'pending'; // 初始状态 this.value = null; // 成功时的返回值 this.reason = null; // 失败时的原因 this.onFulfilledCallbacks = []; // 成功回调队列 this.onRejectedCallbacks = []; // 失败回调队列 // 成功时调用的方法 let resolve = (value) => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; this.onFulfilledCallbacks.forEach(fn => fn(this.value)); } }; // 失败时调用的方法 let reject = (reason) => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; this.onRejectedCallbacks.forEach(fn => fn(this.reason)); } }; try { executor(resolve, reject); // 立即执行传入的执行函数 } catch (error) { reject(error); // 如果执行函数抛出异常,Promise立即变为rejected状态 } } // Promise原型上的then方法 then(onFulfilled, onRejected) { onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value; onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason; }; let promise2 = new MyPromise((resolve, reject) => { if (this.state === 'fulfilled') { // 创建一个微任务等待promise2完成初始化 queueMicrotask(() => { try { let x = onFulfilled(this.value); this.resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }); } else if (this.state === 'rejected') { // 同样创建微任务等待promise2完成初始化 queueMicrotask(() => { try { let x = onRejected(this.reason); this.resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }); } else if (this.state === 'pending') { // 当异步操作未完成时,将回调函数保存到对应回调数组中 this.onFulfilledCallbacks.push((value) => { try { let x = onFulfilled(value); this.resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }); this.onRejectedCallbacks.push((reason) => { try { let x = onRejected(reason); this.resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }); } }); return promise2; } // 处理promise2的决议逻辑 resolvePromise(promise2, x, resolve, reject) { // 防止then方法被多次调用 if (promise2 === x) { return reject(new TypeError('Chaining cycle detected for promise')); } // x为null或x不是对象或函数时,直接用x的值解决promise2 if (x === null || typeof x !== 'object' && typeof x !== 'function') { return resolve(x); } // 解决Promise之间的循环引用问题 let called; try { // 判断x是否有then方法,如果有则将x视为Promise let then = x.then; if (typeof then === 'function') { then.call(x, y => { if (called) return; called = true; this.resolvePromise(promise2, y, resolve, reject); }, r => { if (called) return; called = true; reject(r); }); } else { resolve(x); } } catch (error) { // 当then方法调用出错时,用error来解决promise2 if (called) return; called = true; reject(error); } } } module.exports = MyPromise; ``` 上面的代码展示了如何从基础开始构建一个简化版的Promise。其核心功能包括: 1. 构造函数中接受一个执行函数,并在内部设置状态、值和失败原因。 2. 成功和失败的回调函数分别绑定到resolve和reject上。 3. then方法用于注册成功或失败的回调函数,它会返回一个新的Promise对象,可以根据前一个Promise的状态决定如何处理。 4. resolvePromise方法用于处理then方法中返回的值,这个值可能是另一个Promise对象,需要特别处理(例如解决Promise的嵌套问题)。 这段代码仅是一个简化版的Promise实现,用于教学目的。真正的Promise规范要复杂得多,包括处理并发、异常捕获和链式调用等多种情况。 在实际应用中,使用JavaScript内置的Promise对象会更为方便和高效,因为它们包含了完整的错误处理机制和优化过的性能表现。但对于学习和深入理解异步编程模型,手写Promise是一个很好的练习项目。