Making HTTP requests is something almost all frontend developers do because of how important data it is to our applications. It is crucial that this is done correctly.
With Angular, you can make use of the built-in httpClient
class imported from @angular/common/http
where you can simply provide an instance of the class in your service. In this write-up, I’m going to be talking about how we can make several seamless HTTP requests using RXJS operators.
Imagine that you are trying to get some data on the load of a page, say, the names of all the students and teachers in a school. One way to do this is by implementing two methods where you can make the HTTP request for both needs respectively, like so:
import { HttpClient} from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Teacher, Student} from '../models';
@Injectable({ providedIn: 'root'});
export class HttpService {
constructor(public http:HttpClient){}
baseUrl = 'https://localhost:4400/api/';
getTeachersNames(): Observable<Teacher[]>{
return this.http.get<Teacher[]>(`${this.baseUrl}/teachers`)
}
getStudentNames(): Observable<Student[]>{
return this.http.get<Student[]>(`${this.baseUrl}/students`)
}
In the above snippet, you can see that we have two methods: getTeachersNames
and getStudentNames
. These two methods return the observables of Teacher
s and Student
s, respectively. We can then subscribe to them and make use of them in our components, like so:
import { OnInit } from '@angular/core';
import { HttpService } from '../services/HttpService.service';
import { Teacher, Student } from '../models';
@Component({
selector: "app-test",
templateUrl: "./test.component.html",
styleUrls: ["./test.component.scss"],
})
export class TestComponent implements OnInit {
// Inject our HttpService which gives us access to the methods
constructor(private globalService: HttpService){}
teachers: Teacher[];
students: Student[];
}
ngOnInit(){
this.globalService.getTeachersNames().subscribe(response => {
this.teachers = response;
});
this.globalService.getStudentNames().subscribe(response => {
this.students = response;
});
}
From the snippet above, I have the httpService
injected into the component, and then I declare two variables: teachers
and students
. These variables are then updated on the init of the component inside the ngOnInit hook by calling the methods in the service.
This is fine and looks very good. However, there is a better way of doing this. Remember, what we want to achieve is to get all the names of teachers and students from the server by calling the provided API. We can optimize this operation by making use of an rxjs operator called zip
. Simply put, zip
emits values as an array after all observables have been emitted. Read more here.
So, we can simply refactor our component like so:
import { OnInit } from '@angular/core';
import { HttpService } from '../services/HttpService.service';
import { Teacher, Student } from '../models';
import { zip } from 'rxjs';
@Component({
selector: "app-test",
templateUrl: "./test.component.html",
styleUrls: ["./test.component.scss"],
})
export class TestComponent implements OnInit {
// Inject our HttpService which gives us access to the methods
constructor(private globalService: HttpService){
const groupedResponse = zip(this.getTeachers(), this.getStudents());
}
teachers: Teacher[];
students: Student[];
}
getTeachers(){
this.globalService.getTeachersNames()
}
getStudents(){
this.globalService.getStudentNames()
}
ngOnInit(){
this.groupedResponse.subscribe(values => {
this.teachers = values[0];
this.students = values[1];
})
}
Notice how I used the zip
operator to combine the two observables and then emit them as an array. The sequence with which the observables are zipped is the exact sequence in which they will be emitted in the array.
This method is useful if you have to make several HTTP requests at the same time in a component, and you need to wait for all requests to be completed before emitting the values.
This is my implementation for making HTTP calls in Angular. Thank you for reading.