From 5ad31283e436157179c859b830b250454ae0567a Mon Sep 17 00:00:00 2001 From: Dominic Farolino Date: Tue, 12 Sep 2023 17:40:26 +0200 Subject: [PATCH 1/4] Add `addTeardown()`. Closes #3. Closes #19. --- README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/README.md b/README.md index f0e275e..0883e2e 100644 --- a/README.md +++ b/README.md @@ -307,6 +307,7 @@ interface Subscriber { undefined next(any result); undefined complete(); undefined error(any error); + undefined addTeardown(VoidFunction teardown); readonly attribute AbortSignal signal; }; @@ -457,6 +458,33 @@ observable.subscribe({next: data => { }, signal: controller.signal}); ``` +#### Teardown + +It is critical for an Observable subscriber to be able to register an arbitrary +teardown callback to clean up any resources relevant to the subscription. The +teardown can be registered from within the subscription callback passed into the +`Observable` constructor. When run (upon subscribing), the subscription callback +can register a teardown function via `subscriber.addTeardown()`. + +If the subscriber has already been aborted (i.e., `subscriber.signal.aborted` is +`true`), then the given teardown callback is invoked immediately from within +`addTeardown()`. Otherwise, it is invoked synchronously: + + - From `complete()`, after the subscriber's complete handler (if any) is + invoked + - From `error()`, after the subscriber's error handler (if any) is invoked + - Unsubscription + +Note that `addTeardown(cleanup)` is just syntactic sugar over the following: + +```js +if (subscriber.signal.aborted) { + cleanup(); +} else { + subscriber.signal.onabort = cleanup; +} +``` + ### Operators From 69e0c81127ccab271c8ec2011254e756d65c0cdb Mon Sep 17 00:00:00 2001 From: Dominic Farolino Date: Wed, 13 Sep 2023 11:12:38 +0200 Subject: [PATCH 2/4] Remove old note --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 0883e2e..7eee5d6 100644 --- a/README.md +++ b/README.md @@ -379,9 +379,6 @@ observable.subscribe({ }); ``` -**Issue**: See https://github.com/domfarolino/observable/issues/3 about having -the Observable constructor being able to register teardown upon unsubscription. - While custom Observables can be useful on their own, the primary use case they unlock is with event handling. Observables returned by the new `EventTarget#on()` method are created natively with an internal callback that From e8fa9fd7a5d392c3105e60b453b002066aefd624 Mon Sep 17 00:00:00 2001 From: Dominic Farolino Date: Wed, 13 Sep 2023 14:56:47 +0200 Subject: [PATCH 3/4] Remove the syntactic sugar analogy The intent with that analogy was to describe how *part* of `addTeardown()` is syntactic sugar over immediately checking `subscriber.signal.aborted`, and *otherwise* setting the given cleanup function to the signal's abort handler, and also invoking it during `complete()` and `error()`, but that latter part was not clear at all and was contradictory as @annevk pointed out. So this commit removes the example, in favor of the earlier descriptive text. --- README.md | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/README.md b/README.md index 7eee5d6..d05e161 100644 --- a/README.md +++ b/README.md @@ -470,17 +470,6 @@ If the subscriber has already been aborted (i.e., `subscriber.signal.aborted` is - From `complete()`, after the subscriber's complete handler (if any) is invoked - From `error()`, after the subscriber's error handler (if any) is invoked - - Unsubscription - -Note that `addTeardown(cleanup)` is just syntactic sugar over the following: - -```js -if (subscriber.signal.aborted) { - cleanup(); -} else { - subscriber.signal.onabort = cleanup; -} -``` ### Operators From 29bb984eae354daea4d60a346a5378c60dcc7433 Mon Sep 17 00:00:00 2001 From: Ben Lesh Date: Wed, 13 Sep 2023 15:51:56 +0200 Subject: [PATCH 4/4] chore: add more information about when teardown occurs. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d05e161..d04a967 100644 --- a/README.md +++ b/README.md @@ -470,6 +470,7 @@ If the subscriber has already been aborted (i.e., `subscriber.signal.aborted` is - From `complete()`, after the subscriber's complete handler (if any) is invoked - From `error()`, after the subscriber's error handler (if any) is invoked + - The signal passed to the subscription is aborted by the user. ### Operators