I'm in a situation where I need execute async functions in "parallel", and continue program execution with the best result. Thus I wrote something like this :
var p = [];
for (var i = 0; i < 10; ++i) (function (index) {
p.push(new Promise(function (resolve, reject) {
setTimeout(function () {
var success = Math.random() > 0.7;
console.log("Resolving", index, "as", success ? "success" : "failure");
success && resolve(index);
}, Math.random() * 5000 + 200);
}));
})(i);
Promise.race(p).then(function (res) {
console.log("FOUND", res);
}).catch(function (err) {
console.log("ERROR", err);
});
Now, I'm wondering if this is good practice when working with promises? Is not resolving or rejecting them more often then anything create memory leaks? Are they all eventually GC'ed every time?
A promise is just an object with properties in Javascript. There's no magic to it. So failing to resolve or reject a promise just fails to ever change the state from "pending" to anything else. This doesn't cause any fundamental problem in Javascript because a promise is just a regular Javascript object.
Since you don't call resolve() , that code will never execute and thus the console will not print "done". The body of the Promise is, however, executed immediately, and since it's empty, there is nothing left for the program to execute!
The main cause of memory leaks in an application is due to unwanted references. The garbage collector finds the memory that is no longer in use by the program and releases it back to the operating system for further allocation.
If it rejects, it is rejected with the reason from the first promise that was rejected. Returns a new Promise object that is rejected with the given reason. Returns a new Promise object that is resolved with the given value.
The only reason this causes a memory leak is because p
is a global variable. Set p = null;
at the end, or avoid using a global variable:
var console = { log: function(msg) { div.innerHTML += msg + "<br>"; }};
Promise.race(new Array(10).fill(0).map(function(entry, index) {
return (function(index) {
return new Promise(function(resolve) {
setTimeout(function() {
var success = Math.random() > 0.7;
console.log((success? "R":"Not r") + "esolving "+ index +".");
success && resolve(index);
}, Math.random() * 5000 + 200);
});
})(index);
})).then(function (res) {
console.log("FOUND: " + res);
}).catch(function (err) {
console.log("ERROR: " + err);
});
<div id="div"></div>
Promises are garbage and cycle collected when nothing holds on to them, which is when your JS and the browser (here setTimeout
) have no references to them anymore.
As soon as one entry in p
succeeds or something fails, whichever is sooner, and setTimeout
will have let go of everything after 5.2 seconds. JavaScript will then happily garbage collect the promises whether they've been resolved, rejected, or neither. No harm.
The only thing you want to avoid is garbage collecting rejected promises, as that is likely to trigger a browser warning because it is indicative of a web programming bug.
Of course, there's a 30% chance none of them resolve, in which case this will leak (until you close the tab).
I think it depends on what the functions are doing. If they are lightweight, then I don't see a problem. If they are doing heavy computations or have side-effects, then they hopefully come with some API to cancel the operations, to help save on resources.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With