---------------------------------------------------------------
Cory Rylan

Nov 15, 2016 
Updated Feb 25, 2018 - 5 min readangular rxjs

This article has been updated to the latest version of Angular 7. The content is still likely be applicable for Angular 2 or other previous versions.

This article has been updated to use the new RxJS Pipeable Operators which is the new default for RxJS 6.

A typical pattern we run into with single page apps is to gather up data from multiple API endpoints and then display the gathered data to the user. Fetching numerous asynchronous requests and managing them can be tricky but with the Angular’s Http service and a little help from the included RxJS library, it can be accomplished in just a few of lines of code. There are multiple ways to handle multiple requests; they can be sequential or in parallel. In this post, we will cover both.

Let’s start with a simple HTTP request using the Angular Http service.



import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http'; @Component({
selector: 'app-root',
templateUrl: 'app/app.component.html'
})
export class AppComponent { constructor(private http: HttpClient) { } ngOnInit() {
this.http.get('/api/people/1').subscribe(json => console.log(json));
}
}

In our app, we have just a single component that pulls in Angular’s Http service via Dependency Injection. Angular will give us an instance of the Http service when it sees the signature in our component’s constructor.

Now that we have the service we call the service to fetch some data from our test API. We do this in the ngOnInit. This is a life cycle hook where its ideal to fetch data. You can read more about ngOnInit in the docs. For now, let’s focus on the HTTP call. We can see we have http.get() that makes a GET request to /api/people/1. We then call subscribe to subscribe to the data when it comes back. When the data comes back, we just log the response to the console. So this is the simplest snippet of code to make a single request. Let’s next look at making two requests.

Subscribe

In our next example, we will have the following use case: We need to retrieve a character from the Star Wars API. To start, we have the id of the desired character we want to request.

When we get the character back, we then need to fetch that character’s homeworld from the same API but a different REST endpoint. This example is sequential. Make one request then the next.

Angular Form Essentials

Learn the essentials to get started creating amazing forms with Angular, get the E-Book now!



import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http'; @Component({
selector: 'app-root',
templateUrl: 'app/app.component.html'
})
export class AppComponent {
loadedCharacter: {};
constructor(private http: HttpClient) { } ngOnInit() {
this.http.get('/api/people/1').subscribe(character => {
this.http.get(character.homeworld).subscribe(homeworld => {
character.homeworld = homeworld;
this.loadedCharacter = character;
});
});
}
}

Looking at the ngOnInit method, we see our HTTP requests. First, we request to get a user from /api/user/1. Once loaded we the make a second request a fetch the homeworld of that particular character. Once we get the homeworld, we add it to the character object and set the loadedCharacter property on our component to display it in our template. This works, but there are two things to notice here. First, we are starting to see this nested pyramid structure in nesting our Observables which isn’t very readable. Second, our two requests were sequential. So let’s say our use case is we just want to get the homeworld of our character and to get that data we must load the character and then the homeworld. We can use a particular operator to help condense our code above.

MergeMap

In this example, we will use the mergeMap operator. Let’s take a look at the code example first.



import { Component } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { mergeMap } from 'rxjs/operators'; @Component({
selector: 'app-root',
templateUrl: 'app/app.component.html'
})
export class AppComponent {
homeworld: Observable<{}>;
constructor(private http: HttpClient) { } ngOnInit() {
this.homeworld = this.http.get('/api/people/1').pipe(
mergeMap(character => this.http.get(character.homeworld))
);
}
}

In this example, we use the mergeMap also known as flatMap to map/iterate over the Observable values. So in our example when we get the homeworld, we are getting back an Observable inside our character Observable stream. This creates a nested Observable in an Observable. The mergeMap operator helps us by subscribing and pulling the value out of the inner Observable and passing it back to the parent stream. This condenses our code quite a bit and removes the need for a nested subscription. This may take a little time to work through, but with practice, it can be a handy tool in our RxJS tool belt. Next, let’s take a look at multiple parallel requests with RxJS.

ForkJoin

In this next example, we are going to use an operator called forkJoin. If you are familiar with Promises, this is very similar to Promise.all(). The forkJoin() operator allows us to take a list of Observables and execute them in parallel. Once every Observable in the list emits a value, the forkJoin will emit a single Observable value containing a list of all the resolved values from the Observables in the list. In our example, we want to load a character and a characters homeworld. We already know what the ids are for these resources so we can request them in parallel.



import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { forkJoin } from "rxjs/observable/forkJoin"; @Component({
selector: 'app-root',
templateUrl: 'app/app.component.html'
})
export class AppComponent {
loadedCharacter: {};
constructor(private http: HttpClient) { } ngOnInit() {
let character = this.http.get('https://swapi.co/api/people/1');
let characterHomeworld = this.http.get('http://swapi.co/api/planets/1'); forkJoin([character, characterHomeworld]).subscribe(results => {
// results[0] is our character
// results[1] is our character homeworld
results[0].homeworld = results[1];
this.loadedCharacter = results[0];
});
}
}

In our example, we capture the character and characterHomeworld Observable in variables. Observables are lazy, so they won’t execute until someone subscribes. When we pass them into forkJoin the forkJoin operator will subscribe and run each Observable, gathering up each value emitted and finally emitting a single array value containing all the completed HTTP requests. This is a typical pattern with JavaScript UI programming. With RxJS this is relatively easy compared to using traditional callbacks.

With the mergeMap/flatMap and forkJoin operators we can do pretty sophisticated asynchronous code with only a few lines of code. Check out the live example below!

Angular Multiple HTTP Requests with RxJS的更多相关文章

  1. [RxJS + AngularJS] Sync Requests with RxJS and Angular

    When you implement a search bar, the user can make several different queries in a row. With a Promis ...

  2. [Angular] Intercept HTTP requests in Angular

    Being able to intercept HTTP requests is crucial in a real world application. Whether it is for erro ...

  3. [Angular] Bind async requests in your Angular template with the async pipe and the "as" keyword

    Angular allows us to conveniently use the async pipe to automatically register to RxJS observables a ...

  4. [Vue-rx] Cache Remote Data Requests with RxJS and Vue.js

    A Promise invokes a function which stores a value that will be passed to a callback. So when you wra ...

  5. [Angular 2] Managing State in RxJS with StartWith and Scan

    The scan operator in RxJS is the main key to managing values and states in your stream. Scan behaves ...

  6. [RxJS] Avoid mulit post requests by using shareReplay()

    With the shareReplay operator in place, we would no longer fall into the situation where we have acc ...

  7. [Angular2 Form] Use RxJS Streams with Angular 2 Forms

    Angular 2 forms provide RxJS streams for you to work with the data and validity as it flows out of t ...

  8. RxJS之Subject主题 ( Angular环境 )

    一 Subject主题 Subject是Observable的子类.- Subject是多播的,允许将值多播给多个观察者.普通的 Observable 是单播的. 在 Subject 的内部,subs ...

  9. RxJS之工具操作符 ( Angular环境 )

    一 delay操作符 源Observable延迟指定时间,再开始发射值. import { Component, OnInit } from '@angular/core'; import { of ...

随机推荐

  1. navicat破解版的下载与激活

    原文链接:http://www.cnblogs.com/djwhome/p/9289295.html 以前一直使用的老版的破解版的navicat,但是最近老是报错 而且连接还特别慢,今天终于不忙了额, ...

  2. 【转】mysql分库分表,数据库分库分表思路

    原文:https://www.cnblogs.com/butterfly100/p/9034281.html 同类参考:[转]数据库的分库分表基本思想 数据库分库分表思路   一. 数据切分 关系型数 ...

  3. H3C 交换机配置ssh登陆

    1.开启ssh服务,创建密钥. <D05-S5048-02>system-view [D05-S5048-02]ssh server enable //开启ssh服务 [D05-S5048 ...

  4. 使用pycharm开发web——django2.1.5(四)视图和模板相关

    刘老师说这块很重要..... 应该是很重要,大概看了一下,这里面关于views中函数作用,大概看来可能就是相应请求,传入数据和跳转,基本功能上貌似这些框架都差不多吧(其实我并没用过3个框架以上.... ...

  5. 第三章 VIVADO 自定义IP 流水灯实验

    第二章里面已经说过了,MIZ701 PL部分没有输入时钟,因此驱动PL资源必须是通过PS来提供时钟,所以这个流水灯实验也得建立一个最小系统了,然后再添加一个流水灯的自定义IP. 3.0本章难度系数★★ ...

  6. Java 8 Collectors 类的静态工厂方法

    摘自<<Java 8 实战>> Collectors 类的静态工厂方法 工厂方法 返回类型 用于 toList List<T>  把流中所有项目收集到一个 List ...

  7. vue采坑之——vue里面渲染html 并添加样式

    在工作中,有次遇到要把返回的字符串分割成两部分,一部分用另外的样式显示. 这时候,我想通过对得到字符串进行处理,在需要特别样式的字符串片段用html标签(用的span)包裹起来再通过变量绑定就好了.不 ...

  8. VBA学习资料分享-5

    工作中经常要从数据库把数据跑出来放到EXCEL上,才能进行下一步的操作,那么除了ADO,还有什么方法可以导入数据库数据呢? 推荐使用QueryTable对象 Dim qt As querytable ...

  9. 基于SDP的提议/应答(offer/answer)模型简介

    1.引入 在松耦合会议中,会话参数完全由会议创建者来确定,参与者能做的仅仅是根据这些会话参数来加入会议(当然也可以选择不加入).这种情况下,主要要做的就是会话描述,在这里SDP本身就足够了. 但是在更 ...

  10. Mac命令行提示

    之前看到一个大神的终端主题好炫,所以自己也想弄一个.看了很多中文的教程都不是很靠谱,效果并没有实现.不能说人家的不对,只能说自己水平有限.后来直接去看 github 上的官方教程,因为是官方嘛~所以肯 ...