Angular 4 Trigger a Subscription Again
If yous trying to build an Angular application in reactive style using RxJs, you will likely run across one of these mutual pitfall scenarios at least once.
In this postal service, we volition get over some common trouble situations, explain why the situation occurs and how to fix it. If yous have used RxJs before, then try to guess the problem in each scenario, just for fun!
Pitfall i - Null Happens
Let's say that we have finished writing a service method, where all the information will be saved to the backend with the click of a button:
We volition plug in a messages component and an error handling service later on to show any error messages that might occur, merely right now we will merely trigger the salvage operation via a click handler:
And there nosotros have it, the Save functionality is implemented. Except that when we try this out, try to guess what happens?
...
Null happened LOL :-) !
But the method is beingness chosen, or so nosotros conclude after some debugging. So what's going on hither?
Pitfall 1 Explanation and how to avoid it
An observable itself is just a definition of a way to handle a stream of values. We can think of information technology as something close to a part. Creating an observable is somewhat like to declaring a function, the function itself is but a annunciation. Calling the part is something entirely different, equally defining a function does not execute its lawmaking.
We demand to telephone call the role in order for something to happen, and that is also the case with an Observable: we need to subscribe to information technology in order for it to work!
Then in order to prepare this issue, we tin exercise the following at the level of the service:
Detect that now we are returning the Observable that we created, while before the Observable was created and the method returned without the Observable being subscribed to.
In the calling component, we can at present add a subscription to this Observable:
At present that we take a subscription, the HTTP lesson creation Mail service call will be sent to the backend as expected, which solves the result.
In order to avert the consequence we need to ensure that nosotros subscribe to the Observables that are returned by the HTTP service, either straight or via the
async pipe.
Sometimes notwithstanding, the issue is not that an HTTP call is non being made, but past the contrary that also many calls are fabricated!
Pitfall ii - Multiple HTTP requests
Speaking of the async piping, let's give information technology a effort, and pass it in some observable that we get back from the service layer. The appreciable will emit a list of lessons:
But wait, yous too desire some fault handling just in instance the phone call fails:
So nosotros add together a subscription to handle the fault, and laissez passer in the observable to the async pipe. So what could take gone wrong here ?
Nada, so nosotros endeavor this out and everything is working. But for whatever reason you lot decide to take a look at the network tab of the Chrome Dev Tools.
And what do you run into ?
... /lessons Get 200 OK ... /lessons GET 200 OK That's correct, duplicate HTTP requests ! The request for reading the data is being issued twice! So what is going on here?
Pitfall 2 Explanation
Information technology turns out that every bit the Observable is merely a definition, let's call back that in a sense its something shut to a function declaration, if we subscribe to it multiple times this ways that each fourth dimension a new HTTP request will be issued, i for each subscription.
Merely like calling a function multiple times gives you multiple render values.
And so if you subscribe multiple times to an an Observable returned by the Angular HTTP Client, that will event in multiple HTTP requests!
The problem this not what nosotros where trying to implement, nosotros want to outcome only i HTTP asking, emit the information and handle errors if they occur otherwise print the data to the screen. Simply what is happening instead is:
- one asking gets back and the information is shown on the screen
- another request is sent to see if an error message volition be displayed
With this scenario if the errors are intermittent it could even happen that the first request goes through and the 2nd gives an error.
How to fix Pitfall 2
So how to fix this? This is ane fashion to exercise it in this scenario:
The shareReplay RxJs operator solves the problem of multiple unintended HTTP requests in an elegant manner, and was added to the RxJs library with the specific example of HTTP requests in mind.
What this operator volition practice, is to ensure that only one HTTP asking will be made to the backend in the beginning subscription, so the upshot of that asking will be served from memory to any other subsequent subscribers.
But no further HTTP requests volition be made, as long as we go on subscribing to the same Observable that we received from the service initially.
This is usually the behavior that we expect from data modification observables that we get back from the service layer: we expect the data modification performance to be done only one time, and the result can be shared with any view subscribers.
We wouldn't want the data modification HTTP request to exist repeated multiple times for every view subscriber, as the data existence saved is exactly the same and that would be redundant.
Its of import to keep in listen this multiple subscription situation when edifice service layers with the HTTP module.
Consider the apply of the shareReplay operator as a practical solution for many of the Observables returned by an Angular HTTP-based service, as this will avoid many unintended HTTP requests in your application.
Another situation that happens not and then much with the HTTP module but with libraries like AngularFire has to with Appreciable completion.
Pitfall 3 - Router gets Blocked?
Imagine that you are building a Router Information Resolver using AngularFire and not the Angular HTTP Library. This issue wouldn't happen with the HTTP library equally we volition encounter in a moment.
As well this router scenario is just an example of the underlying problem, that could manifest itself in other ways. The goal of the data resolver is to load some data before the routing transition completes, this way the data is already available when the new component gets rendered.
Let's have a look at some router configuration for a information resolver:
This configuration means that if we hit a url /edit we will load a
EditLessonComponent, simply before nosotros are going to load some information starting time: a list of lessons. For that we ascertain a router information resolver:
Now that we have finished implementing our resolver, we try to trigger the router transition where the resolver is applied, and and then attempt to estimate what happens?
...
Over again, nothing happened! The router transaction did non occur, nosotros stay at the original screen and the UI does not go updated. Its like the transition was never triggered. What could take happened here?
Pitfall 3 Explanation
This has to practise with both the style the router works and the mode the AngularFire observable API works. The router in this instance will accept the observable that we returned and it will subscribe to it. Then it will wait for the data to arrive and for the Observable to complete, and only then the route transition is triggered.
This is because the router needs the data to be available before instantiating the target component.
After all, the master goal of the data resolver is to retrieve the information so that the data is ready available when the target component gets created.
So this means that if nosotros return an appreciable in a information resolver, we demand to ensure that not only information technology fetches the datan but also that information technology completes, then the router knows that the data is ready.
The router does not presume that the Observable volition emit merely one value, and it volition wait for the Appreciable to to either complete or error out before it completes the routing transition.
Just the question is, how can nosotros ensure that our observable ever completes? In this case we can for example simply telephone call the first() or take(1) operators and create a derived appreciable that completes afterward the first value is emitted:
Ever keep Observable completion in mind
With this the route navigation will complete successfully. This router scenario is but ane possible manifestation of what can happen if we accidentally overlook Observable completion.
Completion is something important to happen in many situations that relate to Observables, take for example the RxJs concat operator: If we pass it an Appreciable that never completes, the concatenation would not happen.
In the case of the Angular HTTPClient module, the returned observables ever emit one value and so complete (unless they error out), then this is why the state of affairs to a higher place would not happen using HTTP Client Observables.
Just in the case to a higher place, considering the AngularFire observables are meant to continuously emit the server pushed information changes of the realtime database, they don't complete after one value gets emitted.
This means that because the Observable will non complete, the router will "hang" the routing transition and the UI will not show the target navigation component.
The solution is to always make sure that the Observables returned past Data Resolvers complete properly, which already implicitly happens for HTTP Observables, just not for AngularFire Observables every bit Firebase Observables are long-lived.
Summary
These are some of the most common RxJs pitfalls that we tin can notice when building Athwart applications:
- forgetting to subscribe, and then nothing happens, like in the case of HTTP Observables
- subscribing likewise many times unintentionally, or not sharing execution results with subsequent subscribers: this tin can very hands happen with HTTP Observables
- forgetting to complete: this does non happen with HTTP observables as they either emit one value and complete or error out, but information technology is prone to happen with long-lived Observables
If nosotros happen to find ourselves in a situation where something is not working as expected, asking these questions will help you find the solution:
- Has this appreciable been subscribed to?
- how many subscriptions does this observable accept?
- when does this observable complete, does information technology consummate?
- Do I need to unsubscribe from this Appreciable?
I promise yous enjoyed the post, I invite you to have a look at the list below for other similar posts and resource on Angular.
I invite you to subscribe to our newsletter to get notified when more posts similar this come out:
And if you would like to acquire a lot more than nigh RxJs, we recommend checking the RxJs In Exercise Course course, where lots of useful patterns and operators are covered in much more detail.
If yous are looking to use RxJs in the specific context of an Athwart awarding, nosotros recommend the Reactive Angular Grade, where we embrace lots of commonly used reactive blueprint patterns for edifice Athwart applications.
If you are just getting started learning Athwart, have a wait at the Angular for Beginners Course:
Other posts on Angular
If you enjoyed this mail, have too a look also at other pop posts that you might find interesting:
- Angular Router - How To Build a Navigation Menu with Bootstrap 4 and Nested Routes
- Angular Router - Extended Guided Tour, Avoid Mutual Pitfalls
- Angular Components - The Fundamentals
- How to build Angular apps using Observable Data Services - Pitfalls to avoid
- Introduction to Angular Forms - Template Driven vs Model Driven
- Angular ngFor - Learn all Features including trackBy, why is it not only for Arrays ?
- Athwart Universal In Exercise - How to build SEO Friendly Single Page Apps with Angular
- How does Athwart Change Detection Actually Piece of work ?
- Typescript 2 Type Definitions Crash Form - Types and Npm, how are they linked ? @types, Compiler Opt-In Types: When To Use Each and Why ?
Source: https://blog.angular-university.io/angular-2-rxjs-common-pitfalls/
Post a Comment for "Angular 4 Trigger a Subscription Again"