2

As it was discussed earlier, JavaScript promises have nothing special with respect to garbage collecting. In the other hand, both async functions and await operations are wrappers around promises. So I wonder whether it is possible for the promise returned from an async function be GCed if no one holds a reference to it and internal awaiting takes too much time?

function getDelayedPromise() {
  return new Promise((resolve) => setTimeout(resolve, someBigNumber));
}

async function bar(data) {
  await getDelayedPromise(data);
  return data;
}

function DOMEventHandler() {
  bar().then(updateUI);
}

(Let's suppose DOMEventHandler sunchronously gets runned to handle some DOM event)

Under the hood, await fulfills then() on the delayed promise to continue function execution after the promise be settled. However, the promise associated with an async function itself (one returned from the bar()) is not placed in the memory in this way. In fact, the spec prescribes to it wait for async function completion to be settled with its value thereafter:

a. Let result be the result of evaluating asyncBody. 
...
d. If result.[[Type]] is normal, then    
   i. Perform ! Call(promiseCapability.[[Resolve]], undefined, « undefined »).
...

(where promiseCapability represents an async function promise)

Is this waiting a guarantee of bar() promise should not be collected before an async function body is evaluated? In other words, is there likelihood that updateUI() will never be executed?

Ilya Loskutov
  • 1,967
  • 2
  • 20
  • 34
  • Something can't be garbage collected if something else depends on it. – Barmar Sep 08 '21 at 16:51
  • 1
    Garbage collection is an implementation detail used to prevent filling up memory. You can ignore it when trying to understand the logic of the code. – Barmar Sep 08 '21 at 16:53
  • @Barmar unfortunately I can't ignore this issue with code like aforementioned one. It might be quite painful if `updateUI()` sometimes would be omitted. – Ilya Loskutov Sep 08 '21 at 17:00
  • 1
    But why would it be omitted? Garbage collection can't change the observed behavior of code. – Barmar Sep 08 '21 at 17:01
  • @Mergasov how would that make sense? `a()` and `b(a())` have distinct different behaviour, so it's never safe to omit executing `a()`. In a similar fashion `c().then(x => d(x))` is not the same as just ignoring the promise from `c()`. – VLAZ Sep 08 '21 at 17:08
  • @Barmar a promise internally keeps its `then()` callbacks to call it after its settling. So if this promise is GCed, these callbacks can't be executed (who can do it?). Did I get something wrong? – Ilya Loskutov Sep 08 '21 at 17:25
  • @Mergasov so, how would it make sense to GC something when you cannot determine if that would alter the program flow? If you GC a promise that doesn't actually have any handlers for resolution/rejection, then it wouldn't make much of an impact (other than freeing some memory). But if you remove a promise that *could* change things, then how do you prove the correctness of the code? – VLAZ Sep 08 '21 at 18:13
  • @Mergasov What I meant by ignoring GC is that it's not allowed to have any visible impact. It makes no more sense to worry about whether a `.then()` callback will be executed than it does to worry about whether `array.map(...).join(...)` will omit calling `.join()`. – Barmar Sep 08 '21 at 18:49
  • @VLAZ I of course agree with you that it's *logically* a wrong idea to GC such promises. But I just find the place in the spec that allows of a sort of doubt. I hope no implementation uses GC in cases like this. – Ilya Loskutov Sep 08 '21 at 18:56
  • @Barmar I finally incline to agree with you. It seems GCing such promises would be a quite pernicious thing. – Ilya Loskutov Sep 08 '21 at 19:03

0 Answers0