2021-12-08 13:29:46
Promise的规范主要基于Promise A+,其核心是定义了Promise的状态机、链式调用规则及异步处理机制;应用上则通过ES6原生Promise类或async/await语法简化异步编程,解决回调地狱问题。 以下是详细说明:
一、Promise A+ 规范核心内容状态机定义
三种状态:
Pending(待定):初始状态,可迁移至Fulfilled或Rejected。
Fulfilled(已兑现):操作成功完成,必须拥有不可变的value值。
Rejected(已拒绝):操作失败,必须拥有不可变的reason错误原因。
状态迁移规则:状态一旦从Pending变为Fulfilled/Rejected,不可逆且不可再次变更。
链式调用(Then方法)
基本结构:每个Promise必须提供.then(onFulfilled, onRejected)方法,接收两个可选函数参数。
返回值处理:
若onFulfilled/onRejected返回非Promise值(如数字、对象等),则下一个Promise直接以该值为Fulfilled状态。
若返回Promise实例,则下一个Promise的状态与其同步(如返回的Promise被Reject,则链式调用进入Rejected分支)。
错误传递:若onFulfilled或onRejected抛出异常,下一个Promise以该异常为reason进入Rejected状态。
异步执行要求
微任务队列:规范要求Promise的回调(如then中的函数)必须通过微任务(Microtask)调度执行,而非宏任务(如setTimeout),以确保异步操作的顺序性。
执行时机:回调函数需在当前执行栈清空后、下一个宏任务开始前执行,例如在事件循环的“检查阶段”触发。
以下是一个简化版Promise的核心代码框架,体现规范中的关键机制:
class MyPromise { constructor(executor) { this.state = 'pending'; this.value = undefined; this.reason = undefined; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; const resolve = (value) => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; this.onFulfilledCallbacks.forEach(fn => fn()); } }; const reject = (reason) => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; this.onRejectedCallbacks.forEach(fn => fn()); } }; try { executor(resolve, reject); } catch (err) { reject(err); } } then(onFulfilled, onRejected) { return new MyPromise((resolveNext, rejectNext) => { if (this.state === 'fulfilled') { setTimeout(() => { try { const x = onFulfilled ? onFulfilled(this.value) : this.value; resolvePromise(x, resolveNext, rejectNext); } catch (err) { rejectNext(err); } }, 0); } else if (this.state === 'rejected') { setTimeout(() => { try { const x = onRejected ? onRejected(this.reason) : this.reason; resolvePromise(x, resolveNext, rejectNext); } catch (err) { rejectNext(err); } }, 0); } else { this.onFulfilledCallbacks.push(() => { setTimeout(() => { try { const x = onFulfilled ? onFulfilled(this.value) : this.value; resolvePromise(x, resolveNext, rejectNext); } catch (err) { rejectNext(err); } }, 0); }); this.onRejectedCallbacks.push(() => { setTimeout(() => { try { const x = onRejected ? onRejected(this.reason) : this.reason; resolvePromise(x, resolveNext, rejectNext); } catch (err) { rejectNext(err); } }, 0); }); } }); }}function resolvePromise(x, resolveNext, rejectNext) { if (x instanceof MyPromise) { x.then(resolveNext, rejectNext); } else { resolveNext(x); }}通过state控制状态不可逆,resolve/reject修改状态并触发回调。
then方法返回新Promise,实现链式调用,使用setTimeout模拟微任务(实际需用queueMicrotask或Promise.resolve().then)。
resolvePromise处理返回值是否为Promise的逻辑,符合规范中的“值穿透”规则。
Generator函数
语法:通过function*定义,使用yield暂停执行,返回迭代器对象。
应用:需配合手动调用next()或co库实现自动执行,早期用于控制异步流程,但已被async/await取代。
示例:
function* gen() { const res = yield fetch('async/await语法
本质:基于Promise的语法糖,async函数返回Promise,await暂停执行直至Promise完成。
优势:以同步代码风格编写异步逻辑,避免回调嵌套,错误处理更直观(可通过try/catch捕获)。
示例:
async function fetchData() { try { const res = await fetch('总结:Promise A+规范定义了异步编程的核心契约,ES6原生Promise及async/await进一步简化了其使用,而简易版实现有助于理解其底层机制。实际开发中,优先使用原生Promise或async/await以获得更好的性能和兼容性。