Promise:三态、链式调用与 thenable 采纳
先理解原理和示例,再练习完整口述与追问。
回答要点
执行器同步、状态只确定一次、回调异步、返回值透传、错误传播、链式循环。
原理拆解
Promise 是一次结算的状态机,then 返回新的 Promise,回调返回值或异常决定后续状态;返回 thenable 还需要安全采纳并防止多次调用和循环引用。回调必须按异步规则执行,不能因为已经 fulfilled 就同步运行。
示例与推演
先测 executor 同步日志与 then 异步日志,再测链式返回普通值、返回 Promise、抛异常、缺失处理器透传和自引用。thenable 若先 resolve 后 reject,只能采纳第一次;读取 then 的 getter 也可能抛错。对每条链画状态与值的流转。
易错点
简化实现没有自动拥有原生全部迭代器组合器、取消或调度优化。严格符合规范需要更系统的兼容测试,面试应准确说明范围。
参考回答可直接练习口述
Promise 保存 pending/fulfilled/rejected 状态,then 必须返回新 Promise;回调正常返回就解析新 Promise,抛错就拒绝。resolve 不能只把 thenable 当普通对象,要采用它的最终结果,同时防止重复回调和链式自解析。下面教学版本提供 then/catch、resolve/reject 与基本 thenable 解析,使用 queueMicrotask 调度;不实现完整原生 Promise、子类 species、finally 或宿主未处理拒绝追踪。
class MiniPromise {
constructor(executor) {
if (typeof executor !== 'function') throw new TypeError('executor 必须是函数')
this.state = 'pending'
this.value = undefined
this.reactions = []
let locked = false
const resolve = value => {
if (locked) return
locked = true
this._adopt(value)
}
const reject = reason => {
if (locked) return
locked = true
this._settle('rejected', reason)
}
try { executor(resolve, reject) }
catch (error) { reject(error) }
}
_settle(state, value) {
if (this.state !== 'pending') return
this.state = state
this.value = value
const reactions = this.reactions
this.reactions = []
for (const reaction of reactions) queueMicrotask(reaction)
}
_adopt(value) {
if (value === this) {
this._settle('rejected', new TypeError('不能解析为自身'))
return
}
const objectLike = value !== null &&
(typeof value === 'object' || typeof value === 'function')
if (objectLike) {
let then
try { then = value.then }
catch (error) { this._settle('rejected', error); return }
if (typeof then === 'function') {
queueMicrotask(() => {
let called = false
try {
Reflect.apply(then, value, [next => {
if (called) return
called = true
this._adopt(next)
}, reason => {
if (called) return
called = true
this._settle('rejected', reason)
}])
} catch (error) {
if (!called) {
called = true
this._settle('rejected', error)
}
}
})
return
}
}
this._settle('fulfilled', value)
}
then(onFulfilled, onRejected) {
return new MiniPromise((resolve, reject) => {
const reaction = () => {
const fulfilled = this.state === 'fulfilled'
const handler = fulfilled ? onFulfilled : onRejected
if (typeof handler !== 'function') {
if (fulfilled) resolve(this.value)
else reject(this.value)
return
}
try { resolve(handler(this.value)) }
catch (error) { reject(error) }
}
if (this.state === 'pending') this.reactions.push(reaction)
else queueMicrotask(reaction)
})
}
catch(onRejected) { return this.then(undefined, onRejected) }
static resolve(value) {
return value instanceof MiniPromise ? value : new MiniPromise(resolve => resolve(value))
}
static reject(reason) { return new MiniPromise((resolve, reject) => reject(reason)) }
}
示例:MiniPromise.resolve(1).then(x=>x+1) 兑现为 2;回调 throw 后可由 catch 接住;then 返回自身形成的直接链式循环会拒绝。执行器先 resolve 一个未完成 Promise,再 reject,也以第一次 resolve 采用的结果为准。恶意 thenable 自己无限产生循环不是本实现承诺解决的情况,不把有限用例通过说成完整规范认证。空间与注册回调及链长有关。Promises/A+:then 与解析过程的定义
返回:前端总清单。