Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RxJS Debugging and Visualisation #237

Closed
cartant opened this issue Nov 1, 2017 · 13 comments
Closed

RxJS Debugging and Visualisation #237

cartant opened this issue Nov 1, 2017 · 13 comments

Comments

@cartant
Copy link

cartant commented Nov 1, 2017

Talk title: RxJS Debugging and Visualisation
Talk length: 20 min
Talk synopsis:

Some months ago, frustrated with the poor tooling available for debugging RxJS applications, I wrote a tool to do the job: rxjs-spy.

It's a tool that I've found useful for application development with NgRx and the engineers at Slack have adopted it for their redux-observable applications.

The talk would cover:

  • the problems with and the previous approaches to debugging RxJS applications;
  • an overview of the tool;
  • some specific debugging scenarios; and
  • a new DevTools integration for Chrome and Firefox.

I am currently working on the DevTools and and anticipate their completion before the December meetup, so BrisJS would be the first place they'd be shown.

Available month(s): Dec
Optional: @ncjamieson

@ichpuchtli
Copy link

YES PLEASE. Awesome work btw rxjs-spy is getting a lot of attention. Should hit up slack for some sponsoring.

@iamkevinv
Copy link
Member

Sounds good :)
Closer to the date i'll reconfirm you're still available for Dec, but this should be added to the Dec lineup. Thanks for submitting!

@ichpuchtli
Copy link

Has BrisJS held a generic "What is RxJS/FRP" yet? I must have missed it.

@iamkevinv
Copy link
Member

We have had #205 which wasn't on RxJS but there was a general concept background provided there.

@ichpuchtli
Copy link

True, I would be happy to prepare a introduction to RxJS and also talk about ReactiveX/IxJS (Pull-Push Iterator) and how they relate.

@iamkevinv
Copy link
Member

Hi @cartant - This still good to go for Dec 4 BrisJS? Looking like a great way to round out the year.

@iamkevinv
Copy link
Member

Yes @ichpuchtli - you could certainly offer a talk! Just pop it into a new issue and we'll get it into scheduling :)

@cartant
Copy link
Author

cartant commented Nov 29, 2017

@iamkevinv Yep. Good to go and looking forward to it.

@iamkevinv iamkevinv changed the title Talk: RxJS Debugging and Visualisation RxJS Debugging and Visualisation Nov 29, 2017
@AshKyd
Copy link
Member

AshKyd commented Dec 9, 2017

@cartant Would you be able to pop your slides and any notes you think would be helpful on the issue? cheers!

@cartant
Copy link
Author

cartant commented Dec 9, 2017

@AshKyd Sure. The slides are here. I will post some notes and some references, tomorrow.

@AshKyd
Copy link
Member

AshKyd commented Dec 9, 2017

You're awesome, thanks

@cartant
Copy link
Author

cartant commented Dec 10, 2017

The slides for the presentation are available here.

However, they are mostly pictures, so here are some notes to accompany them:

Slides 1 to 3

This proposal introduces an Observable type to the ECMAScript standard library. The Observable type can be used to model push-based data sources such as DOM events, timer intervals, and sockets. In addition, observables are:

Compositional: Observables can be composed with higher-order combinators.
Lazy: Observables do not start emitting data until an observer has subscribed.

Slides 4 to 6

  • Numerous frameworks and libraries use observables and RxJS:
  • It's also possible that you have an observable in your application without knowing it, as the Redux store implements a Symbol.observable property.
  • RxJS aims to be a reference implementation for the TC39 observable proposal.
  • The proposal is at stage 1 and is considered ready for stage 2.
  • The proposal has a long way to go, but there is interest in adding observables to browser implementations - which is likely to have a positive influence on the TC39 process.

Slides 7 and 8

  • Debugging observables is not straightforward due to the way in which they are composed.
  • Breakpointing and stepping through the composition is not useful, as nothing interesting is going to occur until an observer subscribes.
  • Many operators don't take a callback, so there's no place to put a breakpoint to intercept a notification.
  • Even if you are able to put a breakpoint within a callback, what if the notification does not make it that far?
  • Some mechanism is needed to facilitate the inspection of notifications.
  • The approach that's usually suggested is to sprinkle do operators throughout composed observables.
  • The do-operator approach involves continually adding (and later removing) code to see what's going on. And it's less than ideal.

Slides 9 to 11

  • When asked by a friend whether there were any tools for debugging RxJS apps, I replied that there weren't and mentioned the do-operator approach.
  • I then started thinking about how a tool could be written to improve the debugging experience.
  • The approach I decided to take was to patch Observable.prototype.subscribe.
  • By patching that one method, the tool is able to intercept every subscription, unsubscription and notification that occurs.
  • The tool also needed a way of identifying observables, so I implemented a tag operator.
  • The tag operator does nothing other than annotate an observable with a string tag. The size and performance impact of the tag operators is minuscule - they are independent of the debugging functionality in rxjs-spy and I often leave them in production code.

Slides 12 to 14

Slides 12 and 14 are identical. Slide 14 was added so that I didn't need to reverse back through code highlights on slide 13. To see the code, press the down arrow on slide 12.

  • Stepping through the example's code:
    • The spy is created and an RxJS Subscription is set up so the the spy and the observables can be torn down when the slide is changed.
    • It's possible to add multiple subscriptions and teardowns to a single RxJS Subscription instance and calling unsubscribe on the instance unsubscribe or tear them down.
    • The DOM events for the slow/fast/stop buttons are wired up using RxJS and the mapTo operator is used so that when clicked the buttons emit a number - the angle through which the image should be rotated.
    • The observables are merged together into a single observable and that observable is shared - so that multiple subscriptions don't effect multiple calls to addEventListener (as fromEvent returns a cold observable).
    • The observable tagged as "increments" emits non-zero changes in rotation for each animation frame. Or, if the change is zero, it never emits.
    • The observable tagged as "angles" uses the scan operator to accumulate the emitted changes into a current angle of rotation.
    • The observable tagged as "readouts" is based on the "angles" observable, but only emits in 15 degree increments and only when the value changes.
    • A subscription is made to the "angles" observable and a transform is applied to the image.
    • A subscription is made to the "readouts" observable and the text is updated.
  • On slides 12 or 14, if you open the DevTools console, you can see rxjs-spy in action:
    • Press the play/slow button to spin the image.
    • In the console, type rxSpy.log("readouts") and you should see the notifications for that observable logged to the console.
    • Type rxSpy.undo() and you should see a list of commands that can be undone.
    • Type rxSpy.undo(1) and the logging should cease.
    • Type rxSpy.show() and you should see a list of the tagged observables.
    • Type deck = rxSpy.pause("readouts") any you should see the updating of the readout paused.
    • Type deck.step() any you should see the readout receive a single update.
    • Type deck.resume() any you should see the updating of the readout resumed.
    • You could also have resumed (and discarded the deck) by calling rxSpy.undo(1).
  • rxjs-spy has more features. Check out the README.md to learn more about them.

Slides 15 and 16

  • Slide 16 uses the same example code as slides 12 and 14, but also wires up the DevTools extension for rxjs-spy.
  • The extension is a work in progress, but there are instructions for its installation in its GitHub repo: rxjs-spy-devtools.
  • The extension's panel lists the observables that have been seen by the spy.
  • This list is filterable by tag or type.
  • Note that it's possible to log and pause observables that do not have tags. Tags are still useful, but as more information is added to the extension's UI, they should become less necessary.
  • To get some idea of the information that the spy provides to the extension, have a look at the communication interfaces. The information includes:
  • When it's ready for release to the Chrome store, the extension will include:
    • a more refined UI
    • more information in the UI
    • a graphical representation of the dependency graph
    • links to the source code with the DevTools

Slides 17 and 18

rxjs-spy has made debugging RxJS applications considerably less frustrating for me. And others found it useful, too. The engineers at Slack have adopted rxjs-spy and have this to say about it:

You might be like, "[...] but aren't Observables impossible to debug?" And you'd have been mostly right less than a year ago. But this is JavaScript and in JavaScript, the only const is change. rxjs-spy makes debugging (i.e. logging and visualizing) streams as simple as adding a tag. A tagged stream can be monitored, paused, and replayed, right from the console.

For anyone interested in reading more about observables and RxJS:

@AshKyd
Copy link
Member

AshKyd commented Dec 12, 2017

Awesome notes, thanks for that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants