Promise的规范和应用

Promise的规范和应用
最新回答
短发过夏

2021-12-08 13:29:46

Promise的规范主要基于Promise A+,其核心是定义了Promise的状态机、链式调用规则及异步处理机制;应用上则通过ES6原生Promise类或async/await语法简化异步编程,解决回调地狱问题。 以下是详细说明:

一、Promise A+ 规范核心内容
  1. 状态机定义

    三种状态

    Pending(待定):初始状态,可迁移至Fulfilled或Rejected。

    Fulfilled(已兑现):操作成功完成,必须拥有不可变的value值。

    Rejected(已拒绝):操作失败,必须拥有不可变的reason错误原因。

    状态迁移规则:状态一旦从Pending变为Fulfilled/Rejected,不可逆且不可再次变更

  2. 链式调用(Then方法)

    基本结构:每个Promise必须提供.then(onFulfilled, onRejected)方法,接收两个可选函数参数。

    返回值处理

    若onFulfilled/onRejected返回非Promise值(如数字、对象等),则下一个Promise直接以该值为Fulfilled状态。

    若返回Promise实例,则下一个Promise的状态与其同步(如返回的Promise被Reject,则链式调用进入Rejected分支)。

    错误传递:若onFulfilled或onRejected抛出异常,下一个Promise以该异常为reason进入Rejected状态。

  3. 异步执行要求

    微任务队列:规范要求Promise的回调(如then中的函数)必须通过微任务(Microtask)调度执行,而非宏任务(如setTimeout),以确保异步操作的顺序性。

    执行时机:回调函数需在当前执行栈清空后、下一个宏任务开始前执行,例如在事件循环的“检查阶段”触发。

二、简易版Promise实现逻辑

以下是一个简化版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的逻辑,符合规范中的“值穿透”规则。

三、ES6+中的异步编程扩展
  1. Generator函数

    语法:通过function*定义,使用yield暂停执行,返回迭代器对象。

    应用:需配合手动调用next()或co库实现自动执行,早期用于控制异步流程,但已被async/await取代。

    示例

    function* gen() { const res = yield fetch('
    https://api.example.com'
    ); console.log(res);}const g = gen();g.next().value.then(data => g.next(data));
  2. async/await语法

    本质:基于Promise的语法糖,async函数返回Promise,await暂停执行直至Promise完成。

    优势:以同步代码风格编写异步逻辑,避免回调嵌套,错误处理更直观(可通过try/catch捕获)。

    示例

    async function fetchData() { try { const res = await fetch('
    https://api.example.com'
    ); const data = await res.json(); return data; } catch (err) { console.error('Fetch failed:', err); }}
四、Promise的应用场景
  • 顺序执行异步任务:通过链式调用确保任务按顺序完成。
  • 并行执行多个任务:使用Promise.all([p1, p2])等待所有Promise完成,或Promise.race([p1, p2])取最先完成的结果。
  • 错误统一处理:在链式调用末尾添加.catch()捕获整个流程中的异常。
  • 资源加载:如图片、脚本的按需加载,通过Promise封装加载状态。

总结:Promise A+规范定义了异步编程的核心契约,ES6原生Promise及async/await进一步简化了其使用,而简易版实现有助于理解其底层机制。实际开发中,优先使用原生Promise或async/await以获得更好的性能和兼容性。