async函数返回的Promise无引用且内部等待过长时是否可被GC?
关于无显式引用的async函数返回Promise是否会被GC回收的解答
核心结论
你给出的示例中,updateUI永远不会出现无法执行的情况,bar()返回的Promise在async函数体执行完成前绝对不会被垃圾回收。
底层逻辑说明
JavaScript的垃圾回收仅会回收没有任何从GC根节点出发的可达引用的对象,GC根节点包括全局对象、正在执行的调用栈、宿主环境维护的活跃任务(比如定时器、未完成的网络请求、DOM事件绑定等)。你的示例中存在完整的可达引用链,保证了所有相关对象都不会被提前回收:
- 首先
getDelayedPromise返回的延迟Promise,内部绑定的setTimeout属于宿主维护的活跃定时器任务,只要定时器未触发、未被主动清除,宿主就会一直持有该定时器的引用,连带持有定时器回调中的resolve函数,而resolve函数本身持有该延迟Promise的引用,因此延迟Promise始终处于可达状态。 - 执行
await getDelayedPromise(data)时,引擎会自动给延迟Promise注册then回调,用于恢复async函数的后续执行。该回调内部持有bar()返回的Promise的决议能力(即规范中提到的promiseCapability,包含resolve、reject方法),因此延迟Promise的可达性会间接保证bar返回的Promise也处于可达状态,不会被GC。 - 你调用
bar().then(updateUI)时,updateUI已经被注册为bar返回Promise的回调,只要该Promise最终被决议,updateUI就会被正常执行。
注意:只有当整条引用链从根节点断开时才会出现逻辑终止的情况,比如你在定时器触发前主动调用clearTimeout清除了定时器,此时延迟Promise的引用被断开,后续逻辑不会执行,但这是主动取消任务的正常行为,和GC无关。
对应示例代码
function getDelayedPromise() { return new Promise((resolve) => setTimeout(resolve, someBigNumber)); } async function bar(data) { await getDelayedPromise(data); return data; } function DOMEventHandler() { bar().then(updateUI); }
内容的提问来源于stack exchange,提问作者Ilya Loskutov
相关产品推荐
相关产品推荐

