I am attempting to write a function that waits for a promise to execute, executes the promise, and then start to wait for the promise to execute again.
I have tried a few looping examples, but all seem to have caused memory leaks.
This is a mock for a library that I am using.
const waitForMessage = (topics, cb) => {
setTimeout(() => {
cb(null, query, "test/request")
}, 250);
}
Which I converted to a standard es6 Promise.
const waitForRequest = () =>
new Promise((res, rej) =>
waitForMessage([], (err, query, topic) =>
err ? rej(query, topic) : res(query, topic)));
And this seems to work fine....
The Problem seems to be when I try iterating over this infinitely...
Conceptually, I would like to do something like this (which has documented issues in the specification)
// Warning: JS implementation will leak memory!!!
const loop = () =>
waitForRequest()
.then(() => loop());
loop();
However, I have found that even a synchronous loop seems to produce a simular memory leak here...
const handleEvent = () =>
waitForRequest()
.then((query, topic) => graphql(schema, query))
.then((data) => {
console.log(`graphql -> recieved data: ${JSON.stringify(data)}`)
})
.catch((err) => {
console.log(`ERROR: ${err}`)
});
const run = async () => {
while (true) {
await handleEvent()
}
}
run();
I sampled the heap profile and found the top down call stack to be...
- [14.5%] emitHook
- [0%] (anon)
- [0%] handleEvent
- [0%] then
- [0%] emitInitNative
- [69.45%] add <- where the majority of the heap is being allocated.
- [0%] waitForRequest
- [0%] Promise
- [0%] (anon)
- [0%] waitForMessage
- [0%] setTimeout
- [16%] insert
Which seems to imply that the .then()
and ultimately the .add()
call is consuming about 70%
of the heap (and growing...). As I sample the heap, it seems as it is growing at a rate of 1-7 kB/s
.
How can squash this memory leak? Or is there a better design pattern to use for this type of situation? Any help is appreciated, still relatively new to using javascript.