Skip to content

Instantly share code, notes, and snippets.

@json2d
Created July 26, 2019 17:48
Show Gist options
  • Save json2d/d9ce21aaa87a17e8f78b2b308da6a94f to your computer and use it in GitHub Desktop.
Save json2d/d9ce21aaa87a17e8f78b2b308da6a94f to your computer and use it in GitHub Desktop.
more technical notes about rxjs

Building observables:

  • Primitives (a.k.a. Kinds of things):

    • Observable:
      • A (subscription) function that takes in an observer, sets up some connections to a data source, and returns a function that can be called to unsubscribe.
        • The actual implementation of Observable is not the subscribe function, but has the subscribe function as a method. It's kind of like how you can make something that represents a function and then say, "But to call it, you need to call its .run method."
        • The actual implementation returns a Subscription object, not an unsubscribe function.
      • Can have a cleanup function internally.
        • Should be called upon unsubscription (cancelling the Observable).
        • Should be called upon error or complete from the data source.
        • next should not be called after it.
        • Is the cleanup function?
    • Observer: Subscribes to (a single) Observable. Has one to three of the following methods:
      • .next(value): Send next value from the Observable.
      • .error(err): Error in the Observable. No more values will be sent.
      • .complete(): Observable finished without error. No more values will be sent.
    • Listener: == Observer
    • Operator: Conceptually: When given an Observable and an Observer, creates an Observer/Observable pair such that the new Observer subscribes to the original Observable, and the new Observable is subscribed to the original Observer. Defining the relationship of the pair defines the operator. Actually: An Observable that, when subscribed to by an Observer, starts emitting to the Observer based on when it receives and based on its own internal logic (mapping what it receives to what it sends). - Compare with Function. The Operator maps input stream to output stream, but some inputs might not create output, and some inputs can result in multiple or delayed outputs.
  • Observables can be constructed from:

    • function: new Observable(subscribe), where subscribe is a function that is called when this Observable is subscribed to. subscribe should take in an Observer and return an unsubscribe callback.
    • Promise: Rx.from(myPromise). Emits the value from the promise when it resolves, and then completes.
    • Observable: Rx.from(myObservable). ? Why does this exist? Is it just for convenience of not typechecking?
    • Array or Iterator: Rx.from([1,2,3]). Emits each value from the array, then completes.
    • Event: Rx.fromEvent(target, eventName, [options and stuff]). Turns an event emitter into an Observable that emits events.
      • Rx.fromEventPattern might exist to customize the eventHandler handling, for custom event systems.
  • Probably a monad?

  • Comparison with Promise:

    • I think Observable is conceptually a generalization of Promise, but isn't practically so: a Promise can't substitute for an Observable (doesn't have the Observable interface), so it's not a subtype of Observable. However, RxJS SEEMS to allow Promises whenever it allows Observables, and you can wrap a Promise in an Observable.
      • However, maybe Observable objects are NOT like Promise objects conceptually, either. They might represent a different layer of abstraction, like addition is not a number.
    • Promises only emit one value.
    • Once they emit the value, asking for the value again will get the same value.
      • If two observers subscribe to the same observable, they might not receive the same values.
        • Wait, then what DO they get? Does only the first one get the values?

== Specific operators ==

  • concatMap(fn: x => obs) concats fn(x0), fn(x1), etc. It's like Array#flatMap(fn: x => arr).
    • E.g. [1,2], [3,4] => [1,2,3,4], waiting for the 2 before it starts on the 3.
      • concatMap listens for observer.complete() to determine when to subscribe to the next stream.
  • mergeMap is similar, except instead of taking all of the first result's items and then the second's, it takes from both streams as the streams emit them.
    • E.g. [1,2], [3,4] can result in [3,4,1,2] if the [1,2] come out very slowly.
  • concatMap(x => [obs0, obs1]) doesn't concatenate obs0 and obs1. It concatenates [obs0, obs1] with the next [obs0, obs1].
    • Say we have concatMap(x => twoValues(x)). If twoValues(0) doesn't ever complete, concatMap will never look at twoValues(1).

== Further reading for Franklin ==

https://blog.angular-university.io/rxjs-higher-order-mapping/ https://redux-observable.js.org/docs/basics/Epics.html https://github.com/ReactiveX/rxjs/blob/master/src/internal/operators/map.ts

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