javascript - 等待但从未解决/拒绝的承诺内存使用情况
问题描述
await
既不解决也不拒绝(从不解决/未完成)的ing会Promise
导致内存泄漏吗?
我在查看带有slorber/awesome-debounce-promise的 React 钩子时对此感到好奇,它创建了新的 Promise,但只解决了最后一个 Promise,因此留下了许多/最不稳定/未实现的。
解决方案
前言(你可能知道这个!):
await
是使用 promise 回调的语法糖。(真的,真的,非常棒的糖。)async
函数是 JavaScript 引擎为你构建承诺链等的函数。
回答:
相关的事情不是承诺是否被解决,而是承诺回调(以及它们引用/关闭的东西)是否保留在内存中。当 Promise 在内存中并且未解决时,它引用了它的回调函数,将它们保存在内存中。有两件事使这些引用消失了:
- 兑现承诺,或
- 释放所有对 Promise 的引用,使其符合 GC 的条件(可能,更多内容见下文)
在正常情况下,promise 的使用者将处理程序与 promise 挂钩,然后要么根本不保留对它的引用,要么只在处理程序函数关闭而不是其他地方的上下文中保留对它的引用。(而不是,例如,将 Promise 引用保存在一个长期存在的对象属性中。)
假设 debounce 实现释放了它对永远不会解决的 Promise 的引用,并且 Promise 的使用者没有在这个相互引用循环之外的某个地方存储引用,那么 Promise 和注册到它的处理程序(以及任何一旦释放对承诺的引用,它们拥有唯一的引用)都可以被垃圾收集。
这需要在实施方面相当小心。例如(感谢Keith将其标记出来),如果 Promise 使用其他 API 的回调(例如,addEventListener
)并且回调关闭对 Promise 的引用,因为其他 API 具有对回调的引用,那防止所有对 Promise 的引用被释放,从而将 Promise 引用的任何内容(例如它的回调)保留在内存中。
因此,这将取决于谨慎的实施,并取决于消费者。可以编写保留对承诺的引用的代码,从而导致内存泄漏,但在正常情况下,我不希望消费者这样做。
推荐阅读
- python - 如何打乱查询集对象字段
- angular - 如何有效地在 angular5 中使用更多 ngIf 语句?
- ocaml - 如何使用 OCaml Containers.CCIO 更改文本
- html - 伪类元素 z-index 问题
- c - 关于从 C 文件中读取字符串
- python - 使用 API 共享密钥在 Azure Blob 存储中获取 Blob
- laravel - 我可以使用名为“资产”的 belongsTo 方法吗?
- android - 从 BackStack 中移除 Fragment 2 并将数据传递给 Fragment 1
- node.js - 在猫鼬查询中选择字段值不等于某物的字段
- python - 在非开放管道上调用读取