question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Using AbortSignal and AbortController

See original GitHub issue

The standards proposals are leaning towards using AbortSignal and AbortController (ala fetch cancellation) for cancellation with Observables. I generally find this favorable for a few reasons and I think I see a migration path for us.

Proposal

  1. Observable subscribe accepts Observer and an optional AbortSignal.
  2. Observable forEach accepts an optional AbortSignal.
  3. The subscriber function for new Observable(subscriber) gives both a safe Observer and an AbortSignal, but is expected to return void.
  4. The Observer passed to subscribe will have an optional abort handler that will get the AbortError if the observable is aborted.
  5. If an abort is triggered on a subscription that happened with forEach, the AbortError would go down the rejection path just like it does with fetch. Since the returned promise is a guarantee to a future where the producer either errors or completes, it makes sense to send the AbortError down the rejection path in this case.

Advantages

  • Synchronous observables cannot firehose and lock up an app, the cancellation semantic exists prioer to subscription.
  • If multiple data producers are set up in a subscriber function (in the Observable constructor), you can add them to the abort signal one at a time, guaranteeing they can be torn down if a subsequent step fails. This wasn’t possible before without some serious hackery.
  • Observables all the way down. Since AbortSignal is an EventTarget, and EventTarget may soon have an on method that returns an observable. you could use abortSignal.on('abort') to compose teardown if you so choose.
  • We will now have the ability to be notified, uniquely, of cancellation (without having to do trickery to figure out if it was really an error or a completion)

Migration path

We’ll start using AbortSignal internally throughout the library.

  1. Add an overload to subscribe that accepts an Observer and an AbortSignal. If AbortSignal is passed, it does not return a Subscription.
  2. Make Subscription into an AbortController
  • Add the ability to create an AbortSignal.
  • Alias unsubscribe as abort.
  1. Have the subscriber function passed to the Observable constructor receive an AbortSignal.
  2. Any function/Subscription returned from the subscriber function (from the constructor), will automatically be added to the AbortSignal.
  3. Remove the observer start method I just added. 😃 lol It’s no longer necessary.
  4. Add the observer abort method that accepts AbortError.
  5. Ensure that aborts arriving at the tail-end of a forEach get sent as rejections of type AbortError to the returned Promise.
  6. BONUS: Have toPromise accept an abort signal
  7. Add deprecation messages for usages that don’t align with the spec.
  8. Long term, I’d like to phase out the 3 handlers method: subscribe(fn, fn , fn), because object literals are more readable anyhow, an forEach can be used for the general case of just needing next. Think subscribe(null, (err) => doAThing(err)) vs subscribe({ error: doAThing }) NOTE: The current TC39 proposal may not reflect this yet

cc/ @jhusain @trxcllnt @kwonoj @mattpodwysocki

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:7
  • Comments:39 (24 by maintainers)

github_iconTop GitHub Comments

3reactions
felixfbeckercommented, Aug 25, 2018

I wrapped my proposal into a library of functions that can be used as drop-in replacement for RxJS factories/operators where AbortSignal makes sense: https://github.com/felixfbecker/abortable-rx

2reactions
felixfbeckercommented, Mar 25, 2020

It’s a bit more nuanced:

  • You need to handle an AbortSignal that’s already aborted, as that will not fire the abort event anymore
  • You need to remove the abort listener if the Observable completes, errors, or gets unsubscribed from, else it’s gonna leak memory (could do this by using takeUntil(fromEvent(signal, 'abort').pipe(take(1))) instead of a Subject)
Read more comments on GitHub >

github_iconTop Results From Across the Web

AbortController & AbortSignal | Can I use... Support ... - CanIUse
Controller object that allows you to abort one or more DOM requests made with the Fetch API. Usage % of. all users, all...
Read more >
AbortController - Web APIs | MDN
Returns an AbortSignal object instance, which can be used to communicate with, or to abort, a DOM request. Instance methods. AbortController.
Read more >
The complete guide to AbortController in Node.js
This tutorial will be a complete guide to the AbortController and AbortSignal APIs. Contents. Introduction to the AbortController API; How to ...
Read more >
How to Cancel Promise with AbortController - LeanyLabs
Now, it's preferred to use AbortController that provides an abort() method that triggers the aborted state of the AbortSignal object obtained from signal ......
Read more >
Create an abortable API using AbortController and AbortSignal
Create an abortable API using AbortController and AbortSignal. Recently I worked on a project that required me to build a typeahead search UI...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found