Qta*_*tax 27 javascript async-await es6-promise
将await荷兰国际集团一个Promise既不做出决议也不废品(从未结算/未实现)引起了内存泄漏?
当我看到带有更高/令人敬畏的反跳承诺的 React钩子时,我对此感到好奇,该钩子创建了新的承诺,但只解决了最后一个,因此使很多/大多数人不安/未实现。
T.J*_*der 14
前言(您可能知道这一点!):
await是用于使用promise回调的语法糖。(真的,真的,真的很好糖)的async功能是在JavaScript引擎构建的承诺链,这样你的函数。
回答:
重要的不是承诺是否已实现,而是承诺回调(以及它们引用/关闭的内容)是否保留在内存中。当promise在内存中并且尚未解决时,它会引用其回调函数,将其保留在内存中。有两点使这些引用消失了:
在正常情况下,promise的使用者将处理程序挂接到该promise,然后要么根本不保留对它的引用,要么仅在处理程序功能关闭而不是在其他地方关闭的情况下保留对promise的引用。(而不是例如,将promise引用保留在长期存在的对象属性中。)
假设debounce实现释放了对它永远不会实现的promise的引用,并且promise的使用者没有在此相互引用周期之外的某个地方存储引用,那么promise和处理程序将向其注册(以及任何它们保留唯一的引用)一旦释放了对Promise的引用,便可以全部收集垃圾。
实施方面需要相当的谨慎。例如(感谢Keith进行举报),如果promise使用其他API的回调(例如addEventListener),并且该回调在对promise的引用上关闭,因为另一个API对该回调的引用,则可能防止释放对承诺的所有引用,从而将承诺所引用的任何内容(例如其回调)保留在内存中。
因此,这将取决于实现的谨慎性以及对用户的影响。可能会编写代码来保留对Promise的引用,从而导致内存泄漏,但是在正常情况下,我不希望消费者这样做。
我使用以下结构进行了一些测试:
function doesntSettle() {
return new Promise(function(resolve, reject) {
// Never settle the promise
});
}
let awaited = 0;
let resolved = 0;
async function test() {
awaited++;
await doesntSettle();
resolved++;
}
setInterval(() => {
for (let i = 0; i < 100; ++i) {
test();
}
}, 1);
Run Code Online (Sandbox Code Playgroud)
在此处实现:https://codesandbox.io/s/unsetteled-awaited-promise-memory-usage-u44oc
仅在Google Chrome浏览器中运行结果框显示开发工具的“内存”标签(但在“性能/ JS堆”标签中却没有)中的内存使用量不断增加,表明存在泄漏。执行此操作但兑现承诺并没有泄漏。
运行此增加的内存使用量对我来说增加了1-4MB /秒。停止运行GC并没有释放任何它。