Angular: HttpClient enforces immutability
Pitfall ahead! HttpHeaders and HttpParams are now immutable.
In a previous story on testing patterns for Angulars new HttpClient API, I wrote that migrating to HttpHeaders
and HttpParams
— from their old counter-parts Headers
and UrlSearchParams
— is “merely a ‘find-and-replace’ of the class names”. That’s not true! Or at least only half of the truth!
With the re-write for @angular/common/http
, the HttpClient API introduces the concept of immutability for requests / responses. The API docs for HttpParams say that explicitly:
This class is immutable — all mutation operations return a new instance.
Best practice: use the fluent builder APIs
When migrating from older code bases, you may have code like the following snippet:
let params = new URLSearchParams();
params.set(`user`, user);
params.set(`password`, password);
With mutable objects, these lines of code alter the state of params
and we have a object with the user and password property! With immutable objects and the new API of HttpParams the above code no longer works! Every call to .set()
now returns a fresh copy of the object — i.e., a copy-on-write strategy. The migrated code must change and should use the builder API for fluent method-chaining:
const params = new HttpParams()
.set(`user`, user)
.set(`password`, password);
The case for immutability — why?
Why? Why you would want immutability? A good and valid question.
First, immutability for data sent over the wire is a common pattern in other platforms, too — one example is the OkHttp client in the Android/Java world.
Second, when sending data over the wire, we let it go over the boundary of our application and enter it into a remote system. Once data has crossed that boundary, it’s published to the world and out of ‘our’ control. By chance, we like data objects in our application to reflect what will be sent in the future or what has been received in the past. To achieve that, we need immutables. Think of it the other way round: when a request has been sent and the request body has been serialized, and after that, we’d modify a request body object, then data locally held in the client diverges from data sent to remote. It will — at some time — turn out to be the cause of silly and avoidable bugs.
I have not found documentation or a talk form the OkHttp authors why they chose immutables. However, the Angular documentation — to my surprise — says quite a lot about the design choice for immutables!
Conclusion
That was devil’s marbles! Don’t fall for that pitfall! I fell for it!
Of course, the other story on medium, the Gist code snippets and the GitHub repository are now updated!