I did a podcast!

James Studdart had me on his podcast, Cynical Developer, to talk about Angular2. It was my first time doing a podcast .. and I got to do it 2 times because of technical difficulties for the first recording. ūüôā Which was actually good for me because the first take was pretty rough (for me) and I needed to organize my thoughts better.

Have a listen if you’re interested, would love to hear your thoughts in the comments!

http://cynicaldeveloper.com/podcast/12/

Share some Observable love (how share() works in Observable + angular2)

Summary

I’m still relatively new to RxJs (5). They have some good documentation (more in progress)¬†but a lot of it is just experience and understanding the mental model. This blog is about the .share() operator and how it impacts angular2 especially regarding the async pipe. The share() operator allows multiple streams to be watched/subscribed but share the same underlying stream so that you only have 1 execution stack (think http calls over the wire where you may have many consumers but only want a single call to be made for the many consumers).

Marbles

First, for common RxJS/stream visuals .. check out RxMarbles. It’s a REALLY good way of visualizing stream operations (which is how I tend to think of Observables … streams to me seems a more natural word for me). That said … no marbles for the share operator….

ASCII Art (lo-tech marbles)

Since there’s no fancy RxMarbles, I’ll resort to lo-tech ASCII diagrams for description here (also for a great intro to streams check out this gist). Out of the box, each subscriber will get its own reference when subscribing to a stream

(stream that has 1, 2, 5 values streaming down)

Subscriber 1:
-----1-----2-----5-----|->

Subscriber 2:
-----1-----2-----5-----|->

The above is a basic example where there is 1 stream and 2 subscribers. Each subscriber will get a copy of the stream and process independently. That allows each to act independently and unaware that anyone else is doing anything, including any ‘side effects’ on the stream like map processing or other operations.

While this is great for keeping consumers consistent and independent, it’s pretty terrible for performance if you are doing things in the stream processing that involve network, heavy latency, or performance intensive computations. This is where .share() comes in. If we take the above diagram and apply .share() to it, it becomes

(stream that has 1, 2, 5 values streaming down)

                         Subscriber 1:
                     /-------|->
                    /
-----1-----2-----5-|
                    \
                     \-------|->
                         Subscriber 2:

If instead of numbers being sent on the stream we think of each number as an operation on the stream to OBTAIN the numbers (such as a map, perhaps deriving some deep mathematical computation like prime number generation) it starts to make more sense in understanding why we want to use share().

Example/Plunker

I have an angular2 plunker that illustrates things. In the plunker I am making an http call with some latency (anywhere from 1-2seconds). I have 2 calls in my angular2 service

    /**
     * Function will return an observable with the data requested. This can be shared across
     * subscribers and will not cause extra http traffic.
     */
    getDataShared(postNum: number): Observable {
        let calls = 0;
 
        return this.http
                   .get('http://jsonplaceholder.typicode.com/posts/' + postNum)
                   .do(
                     () => {
                       console.log("side effect on shared");
                     }
                   )
                   .map(
                      (res) => {
                        let json = res.json();
                        calls++;
                        json.networkCalls = calls;
                        console.log(JSON.stringify(json));
                        return json;
                      })
                   .share();
 
    }
    /**
     * Function will return an observable with the data requested.
     * There is no share operator used here so each subscriber will result in the entire stream firing.
     */
    getDataNotShared(postNum: number): Observable {
        let calls = 0;
 
        return this.http
                   .get('http://jsonplaceholder.typicode.com/posts/' + postNum)
                   .do(
                     () => {
                       console.log("side effect on not shared");
                     }
                   )
                   .map(
                      (res) => {
                        let json = res.json();
                        calls++;
                        json.networkCalls = calls;
                        console.log(JSON.stringify(json));
                        return json;
                      });
 
    }

I also have bindings via the async pipe in angular2

 <table class="table">
   <tr><td>UserID:</td><td>{{(dataServiceObservableNotShared | async)?.userId}}</td></tr>
   <tr><td>ID:</td><td>{{(dataServiceObservableNotShared | async)?.id}}</td></tr>
   <tr><td>Title:</td><td>{{(dataServiceObservableNotShared | async)?.title}}</td></tr>
   <tr><td>Body:</td><td>{{(dataServiceObservableNotShared | async)?.body}}</td></tr>
 </table>
 <table class="table">
   <tr><td>UserID:</td><td>{{(dataServiceObservableShared | async)?.userId}}</td></tr>
   <tr><td>ID:</td><td>{{(dataServiceObservableShared | async)?.id}}</td></tr>
   <tr><td>Title:</td><td>{{(dataServiceObservableShared | async)?.title}}</td></tr>
   <tr><td>Body:</td><td>{{(dataServiceObservableShared | async)?.body}}</td></tr>
 </table>

If you run this example and look at the browser console what you’ll see is that for the NON shared stream the stream reaches all the way back to the originator of the data, the http call, for EACH subscriber (the subscriber is the binding in angular2 via the async pipe).

side effect on not shared
{"userId":1,"id":3,"title":"ea molestias quasi exercitationem repellat qui ipsa sit aut","body":"et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut","networkCalls":1}
side effect on not shared
{"userId":1,"id":3,"title":"ea molestias quasi exercitationem repellat qui ipsa sit aut","body":"et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut","networkCalls":2}
side effect on not shared
{"userId":1,"id":3,"title":"ea molestias quasi exercitationem repellat qui ipsa sit aut","body":"et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut","networkCalls":3}
side effect on not shared
{"userId":1,"id":3,"title":"ea molestias quasi exercitationem repellat qui ipsa sit aut","body":"et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut","networkCalls":4}

You can also see that the ‘side effect’ processing is called 4 unique times. While this may be great in some cases, it is clearly NOT good when talking over high latency operations, such as http, or with code that is CPU intensive. What we’d prefer to do is share the stream across all subscribers and re-use the upstream processing – only consume the end result. This is what the .share() operator does.

side effect on shared
{"userId":1,"id":3,"title":"ea molestias quasi exercitationem repellat qui ipsa sit aut","body":"et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut","networkCalls":1}

You can also notice the very real side-effect of the 2 different stream processing types by looking at the latency generated when binding the UI. Since there are 4 different http calls being made in the non-shared example and only a single call in the shared example the UI itself demonstrates how dramatic the binding time is. Check out the below animation

share operator on stream processing

You can see I put the post number ‘3’ into the non-shared stream and each area of the UI where I have an async pipe doing the binding is binding individually and slowly. This is because there is a network call taking place for EACH async pipe. Whereas the shared stream makes 1 call and the ENTIRE UI binds in 1 operation afterwards. You can also see the console logs indicate that my ‘side effect’ is taking place multiple times for the non-shared stream whereas for the shared stream you notice 1 ‘side-effect’ taking place.

Conclusion

The share() operator isn’t applicable in all cases, but for angular2 UI binding when utilizing the async pipe I believe it’ll be used on MOST cases where a single underlying stream is used. ESPECIALLY for angular services that make http calls.

I hope this helped you understand the share() operator in RxJS and also how it impacts performance for any consumer especially angular2 and the async pipe.

Thanks for reading!

HTML5 and Docker

Summary

If you’ve ever messed with UI programming that utilized the ‘hash’ URL technique for invoking UI actions, it’s time to go html5 native!

This blog post will describe how to setup an apache docker container with the pieces enabled for URL Rewriting. This allows html5 ‘pushState’ to be utilized instead of hash operations. Some advantages HTML5 pushState offers¬†over hash:

  • Cleaner looking for sharing URLs (http://…/#/employees/list vs http://…/employees/list)
  • Search Engine Optimized (SEO) due to being able to pre-generate/crawl your site and return things server-side whereas hash always needs to process on the client and is not SEO friendly

The major disadvantage is that it requires the server being involved .. that’s where this post comes in.

NOTE: For angular2, there is a debate going on for what the default should be, hash or html5. You can read about it here.

Setup

I have a little toy project I have been using for a few years for Spring Boot and angular to help me prove out concepts. I won’t go into any detail on the UI itself (I recently converted from angular1 -> angular2 and that’s what drove this blog post, but it’s applicable for any UI tech that utilizes hash URLs).

NOTE: All code is in the my git repo.

To try everything out you’ll need a recent version of docker installed. If you are using an ubuntu/debian based distro you can install it with:

$ curl -sL https://deb.nodesource.com/setup_5.x | sudo -E bash -
$ sudo apt-get install -y nodejs

From here you need a Dockerfile like-so:

# Pull base apache image
# ---------------
FROM httpd:2.4
 
# Maintainer
# ----------
MAINTAINER Jim Basilio &lt;jim.basilio@gmail.com&gt;
 
# Copy file in as daemon user
USER daemon
 
# httpd.conf turns on rewrite module and rewrites 404 errors to load index.html then redirect client
COPY ./httpd.conf /usr/local/apache2/conf/httpd.conf
 
USER root
 
# Define default command to start bash. 
CMD [ "httpd-foreground" ]

What this does is build a docker image and copy in httpd.conf that turns on the urlrewrite module and configures the rewrites when a 404 is encountered.

For example, when a user goes to your app at http://awesomeapp.com that allows index.html to load angular (or whatever UI framework you are running) and then angular takes over managing client routing. On a later session when a user ‘direct links’ to your app at http://awesomeapp.com/users/list, this is making a server request to apache (in this case) to serve the ‘users/list’ folder (looking for an index.html normally). However, we don’t have that folder on our server since it really was a UI route so a 404 would be returned from apache.

The urlrewrite rule is

    Options +FollowSymLinks
    IndexIgnore */*
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule (.*) index.html

I didn’t originally write the above, I took it from this SO gist. When the above is read by apache, any 404 errors that are found will rewrite the URL so index.html is served and then angular will perform the routing it needs. From the users perspective all of this is seamless and it just “does the right thing”. Without this in place, the users direct link would result in a “404 not found” and a very confused user. To start the container you can run:

$ sudo docker run -d -v <span class="pl-s"><span class="pl-pds">$(</span><span class="pl-c1">pwd</span><span class="pl-pds">)</span></span>:/usr/local/apache2/htdocs --name=html5-apache -p 8080:80 -t html5-apache

Be¬†sure¬†to customize the ‘$(pwd)’ with whatever the root is for your application.

That’s it! You now have a docker image you can use for any app that requires html5 pushState routing. This is a good alternative to using ‘lightweight’ dev http servers as seen with angular2 development stacks. You can start the container and let it run, adjusting the shared volume with your source code (i.e. delete the files, change the files, whatever) and when you reload your site everything will instantly update.

I’m using this setup for my hiit-frontend project¬†which is working great. I can run an ‘npm run build’ and it’ll recompile all my typescript and move my site to the ‘dist’ folder. The dist folder is my shared volume to docker which I just leave running all the time (I intend on writing more about angular2 and the build stack I’m using there in another blog post).