Tag Archives: RxJS

I’ve built my first Angular2 app!

I developed my first Angular2 app! That is quite an achievement since initially, I was against Angular2 mainly because it didn’t look like JavaScript (it’s framework, it uses TypeScript, its weird template syntax). I still do not prefer it, but I said to myself that a knowledge of a new technology will make me cooler to future head hunters and that I will have a great perspective on React vs. Angular debate.

This app is about displaying food/ingredients in a table format and providing a menu where you can filter it by their name as well as their property (for example category – if they are vegetables, fruits, beverages, …). I came with idea while educating myself about SCD diet and noticed existing sites make it hard to see all food with a certain common property. For example, if I wanted to see all fruits I needed to scan all lists from A to Z and for all food see if it’s fruit or not ((I found one at later time that’s little interactive: it’s here.)). The app is definitely not a finished project, it will grow as a needs arise (I will not build it primarily for the sake of learning Angular). You can find it on GitHub.

I scaffolded an Angular2 app with angular-cli and decided to use SemanticUI toolkit for appearance.

  • The first step was to make it functional as soon as possible (meaning developing in a unmaintainable way).
  • The second step was making it more in FP style.
  • The third step was a refactoring where I used RxJS which Angular features by default and which I greatly admire (more complex than classic autocomplete example, it was the most enjoyable part while developing the app so far).
  • Lastly, I refactored one big component into smaller components that communicate with each other via RxJS Observables. You can see this in project’s commit history.

I was only little annoyed while using TypeScript. Because I wrote a lot of functions I needed to annotate them with types otherwise TypeScript complained (that was not the problem if I didn’t use functions). Very big concern was when I discovered that Ramda, my go-to FP library, in TypeScript doesn’t support special placeholder which I was so used to – I solved this issue with a different design but nonetheless.

redux-observable is epic, goodbye redux-thunk and axios

Redux-observable is alternative way of performing async operations in JavaScript applications that use redux, apart from redux-thunk. And certainly more awesome. It uses RxJS underneath which I already wrote about briefly. Apart from bringing the power of functional reactive programming into my application I also see it as a way to better structure my application (while using epics). And I also discovered that for making requests to back-end I don’t need to import special library anymore because RxJS includes that too (Rx.Observable.ajax). So goodbye axios, you’ve been a very good friend to me the last couple of months, but I’ve moved from promises to observables.

What is it?

The core principle of redux-observable is this: When you dispatch a redux action that will do some async stuff, this action first goes through your normal reducer and after new state has been created, redux-observables sends this action into a stream and applies all your defined epics to it.

Epic is a function that takes an action and returns actions, for example in case of success and/or failure. It’s important to know all possible actions in your application goes through this stream. So you want to filter action to specific type and then perform async stuff possible based on action payload. Simple epic might look like this:

const searchEpic = (action$, store) =>
  action$.ofType('SEARCH')
    .map(action => action.payload)
    .debounceTime(400)
    .switchMap(query => 
      ajax.post('http://localhost:8080/search', {query})
        .takeUntil(action$.ofType('CANCEL_SEARCH')))
    .map(res => ({type: 'SEARCH_DATA', result: res.response}))

OK, it’s not that simple but if it were too simple than it won’t be worth using RxJS. 😀

Little cookbook

1 How do you dispatch sequence of actions from same epic?

const epic = (action$, store) =>
  action$.ofType('ACTION_TYPE')
    .mergeMap(res => Observable.of(actionCreator1, actionCreator2))

Read this for more.

2 How do you perform parallel requests like axios.all?

Observable.forkJoin(
    Observable.DOM.ajax.getJSON(`/users`),
    Observable.DOM.ajax.getJSON(`/likes`),
    (users, likes) => ({
      users: users.data,
      likes: likes.data
    })

Note that the last argument to forkJoin is optional and is a selector which parameters are ordered correspondingly to requests. In case if you miss axios.spread.

Autocomplete in RxJS (code walk)

Autocomplete functionality is probably the first use case you hear for using RxJS. Here is one possible implementation for it (code can be also found in JSBin):

let input = document.querySelector('input')
let inputStream = Rx.Observable.fromEvent(input, 'input')

let ul = document.querySelector('ul')

let responseStream = inputStream
  .debounceTime(500)
  .map(e => e.target.value)
  .filter(value => !value | value.length > 2)
  .distinctUntilChanged()
  .flatMap(
    value => value ? Rx.Observable.fromPromise(axios.get(`/states?q=${value}`)) : Rx.Observable.of({data: []})
  );

responseStream.subscribe(({ data }) => {
  ul.innerHTML = data.map(state => `<li>${state}</li>`).join('')
})
    In plain English, when user type into input field:

  1. we first wait that user finishes with typing (this happens when there is no new typing for some amount of time, say 500 ms).
  2. Secondly, we extract value from input.
  3. If value is not at least 3 characters long or empty, we ignore it and stop with the flow.
  4. Otherwise we compare its value and if it’s the same as the last time user finished typing, we ignore it and stop the flow since these values aren’t distinct. There is no point in abusing the server if result is already there.
  5. If distinct, we make the request. But only if value is not empty. If latter, we just return observable that emits object with empty data. Because again, no need for abusing the server if the output is known. Also if we wouldn’t have control over empty values than server would return all records. Which is not the desired effect.
  6. Lastly, we subscribe to the input observable and based on data generate list and attach it to DOM