Reputation: 529
I'm trying to figure out whether a memory leak can be created by an async function that never resumes. For example:
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function Test() {
this.arr = [];
this.alloc = async function() {
for (i = 0; i < 300000; i++) {
this.arr.push(document.createElement('div'));
}
await timeout(10000);
alert('done waiting ' + this.arr.length); // outputs 300000
};
};
var test = new Test();
function leak() {
test.alloc();
test = null;
window.gc(); // Running chrome with expose-gc flag
// Snapshotting memory here shows divs have been deallocated
}
Using Chrome's memory tools, I grabbed a snapshot when this code finishes executing. I would have expected to see 300000 HTMLDivElements still allocated, but lo and behold - the memory seems "freed". What's strange is if I try to access the array contents they are still there. Can anyone explain this phenomenon?
Upvotes: 2
Views: 438
Reputation: 665344
If I replace someForeverPromise with a timer and then try to access the array contents they are still there
Your someForeverPromise
itself was garbage-collected, and with it all the callbacks that were still waiting for it - including the resumption of the async function
.
You can use
const foreverPendingPromise = new Promise(resolve => {
global.reference = resolve;
});
where the global reference
keeps up a way to resolve the promise to prevent the callbacks from being garbage-collected. (You also should make sure that no-one accidentally calls reference
to ensure it stays pending, but I'll leave that as an exercise to the reader).
Upvotes: 1