Tha*_*thy 2 javascript rxjs angular
我想使用传递不同 id 的同一端点进行多个 HTTP 调用。有没有更好的方法从 UI 处理这个问题。目前无法更改后端,有更好的方法吗?
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, forkJoin } from 'rxjs';
@Component({
selector: 'app-root',
templateUrl: 'app/app.component.html'
})
export class AppComponent {
loadedCharacter: {};
constructor(private http: HttpClient) {}
ngOnInit() {
let character1 = this.http.get('https://swapi.co/api/people/1');
let character2 = this.http.get('http://swapi.co/api/people/2');
forkJoin([character, character2]).subscribe(results => {
// results[0] is our character
// results[1] is our character2
});
}
}
Run Code Online (Sandbox Code Playgroud)
您可以提取逻辑以在公共函数内创建可观察的内容并按如下所示使用它:
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, forkJoin } from 'rxjs';
@Component({
selector: 'app-root',
templateUrl: 'app/app.component.html'
})
export class AppComponent {
loadedCharacter: {};
constructor(private http: HttpClient) {}
ngOnInit() {
let character1 = this.createHttpObservable('1');
let character2 = this.createHttpObservable('2');
forkJoin([character, character2]).subscribe(results => {
// results[0] is our character
// results[1] is our character2
});
}
createHttpObservable(id:string) {
const url = 'https://swapi.co/api/people/';
return this.http.get(`url${id}`);
}
}
Run Code Online (Sandbox Code Playgroud)
基本上有两种选择:
是您用来forkJoin()将所有可观察量组合到数组中的选项
subscribe()forkJoin发出值您可以使用mergeMap()您的 ID 并在其中一个可观察量完成时做出反应
.subscribe()稍微不同的方式处理你的发射值最终,您需要决定哪种方法最适合您。您的实施没有任何问题。我注意到你将你的loadedCharacter作为一个对象,所以说实话,选项 2 可能适合你的用例
选项 2的示例代码。请参阅此stackblitz的小演示:
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, from, Subject } from 'rxjs';
import { mergeMap, takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-root',
templateUrl: 'app/app.component.html'
})
export class AppComponent {
private endSubs$ = new Subject();
loadedCharacter: {};
constructor(private http: HttpClient) {}
ngOnInit() {
/* ids of all the characters you want to load*/
const characterIds = [1, 2];
/* this will emit each id as a value */
from(characterIds).pipe(
/* merge each id to an Observable of the http get request */
mergeMap(id => this.http.get(`https://swapi.co/api/people/${id}`)),
/* cancel any pending requests when the component unloads.
this will avoid any RxJS memory leaks */
takeUntil(this.endSubs$)
).subscribe(
character => {
/* note that you will only receive 1 character at a time */
console.log('received character', character);
this.loadedCharacter[character.id] = character; // or whatever you want to do
},
err => console.log('Error loading a character', err),
() => console.log('All character requests have finished')
);
}
/* clean up our subscriptions when the component destroys */
ngOnDestroy() {
this.endSubs$.next();
this.endSubs$.complete();
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:我添加了一些 RxJS 清理代码以避免mergeMap. 卸载此组件时任何待处理的请求都将被取消。这是一个示例 SO 答案,解释了 Observable 清理,这是一篇相关的 RxJS 文章,介绍了将takeUntil().