Create an Observable-Based Fetch Wrapper Using Ramda & Most

InstructorJosh Burgess

Share this video with your friends

Send Tweet

Unlike RxJS, Most does not include an observable-based AJAX helper utility. However, it can be very convenient to have one, because it allows you to use streams to do things like declaratively handling errors & setting up cancellation. In this lesson, we use currying & functional composition to create an Observable-based wrapper around the fetch API with Ramda & Most.

Vinny
~ 7 years ago

Is there a particular advantage to using Most.JS as a reactive lib as opposed to using RxJS ?

Josh Burgessinstructor
~ 7 years ago

Is there a particular advantage to using Most.JS as a reactive lib as opposed to using RxJS ?

Good question. First, you can read the authors' own words about why you might choose Most here:

Why most.js for Reactive Programming?

Now, I'll give you my opinion, in my own words:

There are 3 major reasons to use Most over RxJS:

  1. Most offers a functional API in addition to a method chaining/fluent API, whereas RxJS only offers a method chaining/fluent API.

The concept is similar to how Ramda & Lodash/fp differ from the regular version of Lodash or Underscore. In Ramda & Lodash/fp, pretty much all functions that take in more than one argument are auto-curried, and the data collection (an array or object) is passed in last. This allows you to create reusable functions by simply only passing in certain arguments and delaying passing in the rest.

Most's functional API works in this same way, but the data collection argument is a stream rather than an array or object. This is important, because it enables you to use a pointfree style where you can use functional composition (ex: via functions like Ramda's compose or pipe) to combine multiple functions together into new functions without having to mention the arguments, which a lot of people find to be more clear & concise. You can see examples of this style here in this lesson on lines 9, 12, & 13. Notice that I created new functionality on those lines without having to write any information about the arguments they take in or how they get passed from one intermediary function to the next.

However, an important thing to note is that the functional API in the current version of Most is not auto-curried. This means that you need to use an auto-curry utility function like curry from Ramda or Lodash/fp on the Most functions if you want to be able to partially apply arguments to them, but this will no longer be the case in the future. Most 2.0 will feature an auto-curried functional API, like Ramda & Lodash/fp (but for streams), where all functions are already curried for you. Here's an example taken from the docs from my redux-most library which explains this:

// Functional & Pointfree style using currying & functional composition
import { compose, curry, pipe } from 'ramda'
import { debounce, filter, map } from 'most'

// NOTE: Most 2.0 will feature auto-curried functions, but right now we must curry them manually.
const curriedDebounce = curry(debounce)
const curriedFilter = curry(filter)
const curriedMap = curry(map)

// someEpic is a new function which is still awaiting one argument, the action$
const someEpic = compose(
  curriedMap(someFunction),
  curriedDebounce(800),
  select(SOME_ACTION_TYPE)
)

// someOtherEpic is a new function which is still awaiting one argument, the action$
// pipe is the same as compose, but read from left-to-right rather than right-to-left.
const someOtherEpic = pipe(
  selectArray([SOME_ACTION_TYPE, SOME_OTHER_ACTION_TYPE]),
  curriedFilter(somePredicate),
  curriedMap(someFunction)
)
  1. Performance.

Most.js is very, very fast. The authors of Most take performance seriously, and this has resulted in Most being, generally, faster, and, at times, SIGNIFICANTLY faster than RxJS 5 & other reactive programming libraries. Please, see the benchmarks here.

  1. Fantasy Land spec compliance.

Another difference between Most and RxJS is that Most implements the Fantasy Land spec. You can learn more about Fantasy Land here. It basically provides a common spec for libraries to define ADTs (Algebraic Data Types) in a way that lets them interoperate with each other seamlessly. You don't HAVE to use this feature at all, but it's nice if you're already using ADTs in other libraries as it opens up a lot of new FP possibilities.

So, it has both a more flexible API and all around better performance. Other than that, it's also a bit more stripped down & minimal (in a good way), and it tends to favor being declarative just a little bit more than RxJS. Most tries to guide you into consistently writing clean, declarative code. Imperative methods are actively discouraged and/or only offered as 3rd party packages outside of the main repo. For example, Subjects are available, but they're in a separate package, because they're an imperative tool and often not needed. There's also a community organization which features other useful & cool, experimental additions.

Hope that helps! :)

Vinny
~ 7 years ago

I truly appreciate your response Josh. After going through Luis Atencio's book Functional Programming in JavaScript - which was a great intro to FP, I still could not figure out how to compose RxJS streams in a pointfree manner. While Rx is declarative in its implementation, I still feel like it doesn't fully adhere to FP paradigms. It's awesome to know that MostJS provides a flexible API that enables one to take advantage of function composition. Bonus points for the performance! I'm really excited to use Most in my future projects. Thanks for the help. I'm looking forward to more of your videos.