javascriptangularpromisegarbage-collection

Are promise handlers cleared from memory after the promise is resolved?


I have an Angular app. I have a service, which has an initialization logic - a backend call to fetch some data. Once the backend call is processed, I resolve a promise, indicating the service is ready to be called. I keep the promise exposed for the whole life of the service/app. Any newly created component using that service checks if the service was initialized (and executes its own init logic), via adding a handler - calling then() on the promise. I can guarantee that only a few handlers are added before the promise is resolved, vast majority of handlers are added after (during the whole life of the app).

Obviously, the promise itself will never be garbage collected. Are the handlers added to the promise cleared (garbage collected) once they are executed? Or will they keep stacking until I run out of memory?


Solution

  • They are cleared from memory.

    When a promise object is fulfilled or rejected, all the then handlers it holds are converted into Promise jobs placed in the Promise Job Queue (the microtask queue in modern browsers), discarding handlers that don't apply.

    This process empties the promise's internal list that held the handlers. The promise jobs, which (each) hold a reference to a handler to be called when run, are removed from the promise job queue when executed and become eligible for garbage collection after job completion. That GC will in turn make the handler (that the job called) eligible for GC unless it's a named function that other code has maintained a reachable reference to.

    Resolving a promise with a promise maintains the resolved promise's list of handlers up until the promise becomes settled and then flushes promise jobs for handlers into the microtask queue or discards unused handlers in normal fashion.

    Basically all handlers are removed from promise internal lists when it becomes settled, either by passing references to them to Promise Jobs created to run them, or discarding handlers not applicable to the promise's settled state.

    If you add handlers to a settled promise, they are processed (or discarded) immediately without being entered into lists of handlers that only pending promises maintain.