1

I plan to use async/await to run many tasks. Since I can't afford to do await on the tasks because main loop will keep spawning new tasks, I need to ensure the promise for the task is destroyed at the end. Does the following code snippet has a leakage of of promises? If there is a better way to achieve this, please let me know too.

const fetch = require ('node-fetch')

var gId = 0;
var ps = {}

var lId = gId; gId ++;
ps[lId] = task(lId)
lId = gId; gId ++;
ps[lId] = task(lId)
//will add many more tasks


async function task(id) {
    console.log("starting..")
    var url = "http://localhost/prod/te.php";
    var r1 = await fetch(url).then((r) => r.text())
    console.log(new Date() + "|" + id)
    await wait(parseInt(r1) * 1000)
    var r2 = await fetch(url).then((r) => r.text())
    console.log(new Date + "|" + id)
    ps[id].then(() => console.log("deleted promise " + id))
    delete ps[id]
}

async function wait(ms) {
    return new Promise (function (resolve, reject) {
        setTimeout(function() {
            console.log("expired")
            resolve(0)
        }, ms)
    })
}
pktCoder
  • 1,105
  • 2
  • 15
  • 32
  • Am not sure if you can cancel a promise that has been fired. although still not sure what exactly your requirement here is to probably help you with alternatives. so here is another SO link that calls for a similar situation (cancel promises), hope it helps https://stackoverflow.com/questions/29478751/how-to-cancel-an-emcascript6-vanilla-javascript-promise-chain – Jaya Jul 01 '18 at 20:19
  • @jaya Thanks for the link. I don't need to cancel the promise, just need it to be completed and destroyed so it won't leak memory. – pktCoder Jul 01 '18 at 20:21
  • Yes it does as you store the promises in a global object. They will stay there until the thread stops – Jonas Wilms Jul 01 '18 at 20:39
  • If you want to ensure the promise is destroyed, why are you storing them in `ps`? – Eric Jul 01 '18 at 21:03
  • The main reason I store them in ps is because I thought calling the `then()` method can cause the promise to come to an end, without it, there may be some resource leakage. By the way, I updated the code snippet with `delete ps[id]`, would that be good enough? – pktCoder Jul 01 '18 at 21:08
  • Also, wonder if there is a way to list all the promises in the system, with which we can check if there is leakage on promises. – pktCoder Jul 01 '18 at 21:09
  • While the question may not be duplicate, [this answer to "Will it cause memory leak when using promise and not rejecting errors?" may help clear things up](https://stackoverflow.com/a/48455154) – Heretic Monkey Jul 01 '18 at 21:14
  • @mike-mccaughan Thanks for the link, it does mention that promise will automatically claimed by the system upon completion --- so I need to cause the promise to complete by the task itself, hence I add the odd-looking code at the end of async function `task`. – pktCoder Jul 01 '18 at 21:19
  • 1
    `delete ps[id]` should do it – Ben West Jul 01 '18 at 21:57

1 Answers1

1

Did some tests and it comes down to, promises will not be leaked at all (which will cause memory leak as I feared). Ran the following code for a long time and the memory consumption on my Mac hovers around 100MB.

const fetch = require ('node-fetch')


var gId = 0;
start()
async function start() {
    var lId;
    var count = 0;
    while (1) {
        lId = gId; gId ++;
        task(lId)
        count ++;
        if (count == 100) {
            count = 0;
            await wait(500)
        }
    }
}


async function task(id) {
    var url = "http://localhost/prod/te.php";
    var r1 = await fetch(url).then((r) => r.text())
    await wait(parseInt(r1) * 1000)
    var r2 = await fetch(url).then((r) => r.text())
}

async function wait(ms) {
    return new Promise (function (resolve, reject) {
        setTimeout(function() {
            resolve(0)
        }, ms)
    })
}
pktCoder
  • 1,105
  • 2
  • 15
  • 32