MCPcopy Index your code
hub / github.com/angular/angular / PromiseStrategy

Class PromiseStrategy

packages/common/src/pipes/async_pipe.ts:61–105  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

59}
60
61class PromiseStrategy implements SubscriptionStrategy {
62 createSubscription(
63 async: PromiseLike<any>,
64 updateLatestValue: ((v: any) => any) | null,
65 onError: ((e: unknown) => void) | null,
66 ): Unsubscribable {
67 // According to the promise specification, promises are not cancellable by default.
68 // Once a promise is created, it will either resolve or reject, and it doesn't
69 // provide a built-in mechanism to cancel it.
70 // There may be situations where a promise is provided, and it either resolves after
71 // the pipe has been destroyed or never resolves at all. If the promise never
72 // resolves — potentially due to factors beyond our control, such as third-party
73 // libraries — this can lead to a memory leak.
74 // When we use `async.then(updateLatestValue)`, the engine captures a reference to the
75 // `updateLatestValue` function. This allows the promise to invoke that function when it
76 // resolves. In this case, the promise directly captures a reference to the
77 // `updateLatestValue` function. If the promise resolves later, it retains a reference
78 // to the original `updateLatestValue`, meaning that even if the context where
79 // `updateLatestValue` was defined has been destroyed, the function reference remains in memory.
80 // This can lead to memory leaks if `updateLatestValue` is no longer needed or if it holds
81 // onto resources that should be released.
82 // When we do `async.then(v => ...)` the promise captures a reference to the lambda
83 // function (the arrow function).
84 // When we assign `updateLatestValue = null` within the context of an `unsubscribe` function,
85 // we're changing the reference of `updateLatestValue` in the current scope to `null`.
86 // The lambda will no longer have access to it after the assignment, effectively
87 // preventing any further calls to the original function and allowing it to be garbage collected.
88 async.then(
89 // Using optional chaining because we may have set it to `null`; since the promise
90 // is async, the view might be destroyed by the time the promise resolves.
91 (v) => updateLatestValue?.(v),
92 (e) => onError?.(e),
93 );
94 return {
95 unsubscribe: () => {
96 updateLatestValue = null;
97 onError = null;
98 },
99 };
100 }
101
102 dispose(subscription: Unsubscribable): void {
103 subscription.unsubscribe();
104 }
105}
106
107const _promiseStrategy = new PromiseStrategy();
108const _subscribableStrategy = new SubscribableStrategy();

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected