The Angular 2 Playground: Part 2 — taking a spin on the merry-go-round

Tom Teman
4 min readApr 28, 2016

--

In the previous article, I gave a lot of background information about the project Itay and I have been working on during weekends for quite some time now.

You can check out the actual code here:

client side
server side

(Bear in mind that it still a work in progress)

Oh, and if you feel like playing…

Just like the view from inside the marry go round, data constantly shifts

Data is updated in all apps, but in a multiplayer game doubly so. Polling the server was not an option. I mean, we could technically do it, and have each player poll the server every <X> milliseconds, but that would raise 2 major problems:

  1. Headache for the user: our users are playing with their mobile phones and it will put a strain on their battery life and data plan.
  2. Motion sickness for the developer: since you want to maintain real-time behaviour, concurrency of the async requests becomes an issue when <X> is small. Especially on mobile (slow connections).

So naturally, we went with socket.io. Besides being a well established library, it plays really really well with the way Angular 2 handles data (more on this later on).

Fetching data is at the core of any web application since time immemorial. Or more precisely the early 90's, culminating recently in the promise object we all know and love from Angular 1.x (and ES2015).

However, promises start to feel like an inadequate solution when you have data that is constantly being refreshed. After all, promises only have a single return value. If you call .then on the promise object after it resolved then you’ll simply get the data it originally fetched. Useful, but not enough.

Also, promises aren’t lazy. As soon as your code defines the promise object, it immediately carries out its executor function.

To illustrate, check out this code snippet (mind it’s in ES2015, so you can run it here):

console.clear();let promise = new Promise(resolve => {
setTimeout(() => {
console.log(‘Promise timeout expired’)
resolve(42);
}, 1000);
console.log(‘Promise started’);
})

even without calling

promise.then(res => console.log(‘Promise resolved’, res));

both console.logs will fire. Once you created the promise it’s eager to get the data right away.

Another lacking feature — you can’t cancel a promise. I can be sorely missed when working with filters and searches.

For example: our user executes ‘search A’, then ‘search B’, but the results for B are returned first, and the results for A subsequently. Therefore, the callback for A is triggered last, resulting in the wrong data being displayed (assuming you have the same callback method for both). Of course there are ways around it. For instance, you can “sign” each request and then compare each response with the current state, and drop it if it is irrelevant. However, make your search dependent on multiple API calls and this turns nasty and fast.

There has to be a better way!

Introducing: Observables

In case you are not familiar with Microsoft’s Rx project:

The Reactive Extensions (Rx) is a library for composing asynchronous and event-based programs using observable sequences and LINQ-style query operators.

Oh, and it’s open source. Yep, it’s an open source Microsoft project. I told ya the early 90’s were a long time ago.

The Angular 2 team decided to “adopt” RxJS (just like it did with Kris Kowal’s Q library when it introduced promises), and so the Observable object just became an integral part of Angular.

The observable object combines the observer pattern, the iterator pattern and functional programming.

You might have also heard of it being referred to as

Reactive Programming

In a nutshell:

  1. Subscribe to async data sequence
  2. Handle each iteration (element) in callback
  3. ….
  4. Profit!

This isn’t anything new. If you’ve ever handled events, it’s the same. After all, events are a constant stream of data (in this case, the event data).

Observables allow you to create data streams of anything, not just click events. In addition, you get an amazing toolbox of functions that allow you to combine, create and filter any of those streams.

For example, when our clients register to a game, they call the feed method:

feed(gameName: string): Observable<Game> {  const gameStream = Observable
.fromEvent(this.socket, ‘game:’ + gameName.toLowerCase() +
‘:feed’)
.map((res: string) => JSON.parse(res))
.map(res => <Game>res.new_val)
.do(this._updateCache.bind(this));
const game =
Observable.fromPromise(this._getGameFromCache(gameName));
return Observable.merge(game, gameStream);
}

Where _getGameFromCache is a simple Promise returning method for quickly getting game data that was already fetched:

private _getGameFromCache(gameName: string): Promise<Game> {
if (!this.gamesCache[gameName]) {
this.gamesCache[gameName] =
this.http.get(`/api/games/${gameName}`);
}
return this.gamesCache[gameName];
}

That solves the first problem with promises: the single return value.

There are plenty of tutorials out there on Observables, so I won’t dive into the code. I’ll simply recommend you try it out.

--

--

Tom Teman

#BUIDLing @ Ethereum Foundation, Account Abstraction (ERC 4337). Previously CEO and founder of Portis (acquired by ShapeShift)