angular - 如何在 Angular 中使用 Observable 获取多个页面?
问题描述
所以我尝试了很多方法,但没有发现。欢迎大家帮忙;我发现了 Angular 和 RxJs。
我有一项服务可以在 swapi API 的许多 URL 上获取资源。我事先不知道会获取多少页。所以我用concat
for eachhttp.get(url)
来创建一个可观察的。
目前,只有第一页数据被添加到组件中(即firstPage
);所有请求都已发送。
export class PeoplesService {
urlSource = "https://swapi.co/api/people/";
pageResponse: GeneralResponse<People>;
fullResponse: Observable<GeneralResponse<People>>;
constructor(private _http:HttpClient) {
}
getPaged(n: number): string {
return this.urlSource + "?page=" + n;
}
fetch(): Observable<GeneralResponse<People>> {
let firstPage = this._http
.get<GeneralResponse<People>>(this.urlSource);
firstPage.subscribe(page => {
this.fullResponse = firstPage; // first page fetched
let pageToDownload = Math.ceil(page.count / page.results.length);
for(let i=2; i<=pageToDownload; i++) {
// Merge all observable (so all request) into one
concat(this.fullResponse,
this._http.get<GeneralResponse<People>>(this.getPaged(i)));
}
});
return this.fullResponse;
}
}
然后我的组件的基本代码如下:
ngOnInit() {
this.peoplesService.fetch().subscribe(r => this.movies = r.results);
// a sort of fetch().onNextFetch(this.movies.push(...r.results)) seems better in this case
// because every data on each pages need to be merged into this.movies
// or sort of fetch().subscribeUntilCompleted(r => this.peoples = r.results) needed I guess
}
我还没有找到可以用来代替订阅的东西(例如当 Observable 已返回所有内容并收集所有内容时的订阅......)。
我猜 subscribe 不会等待 Observable 的“onCompleted”状态,并且不会每次都调用它来获取所有返回值。那么如何获取所有数据呢?
有什么东西可以让 Observable 像流一样工作并将其通过管道传输到this.peoples.push(...r.results)
?我不知道我是否走在正确的轨道上。
解决方案
好的,经过几个小时的工作,我找到了答案。我用来mergeMap()
从第一个 Oservable 获取数据并将merge()
所有 Observable 合并为一个。
import { HttpClient } from '@angular/common/http';
import { Observable, merge } from 'rxjs';
import { take, map} from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class PeoplesService {
private getPaged(n: number): string {
return this.urlSource + "?page=" + n;
}
/**
* Return an array with the natural number in it.
* @param size : size
* @param start : first number
* Examples :
* naturalNumberArrayFactory(3) returns [1, 2, 3]
* naturalNumberArrayFactory(3, 2) returns [3, 4, 5]
*/
protected static naturalNumberArrayFactory(n: number, start = 1): number[]{
return [ ...Array(n).keys() ].map(x => x + start);
}
fetch(): Observable<GeneralResponse<People>> {
return this._http
.get<GeneralResponse<T>>(this.urlSource)
.pipe(take(1), map(firstPage => {
// Amount of page to get ( -1 because got firstPage)
let pageToDownload = Math.ceil(firstPage.count / firstPage.results.length) - 1;
// Generate array ids and replace them with GET requests
let observables = GenericService.naturalNumberArrayFactory(pageToDownload, 2)
.map(id => this._http.get<GeneralResponse<T>>(this.getPaged(id)));
// Add the first page to avoid to repeat the request
observables.unshift(of(firstPage));
return merge(...observables);
}));
}
}
推荐阅读
- reactjs - 使用 fetch 方法做出反应和承诺问题
- reactjs - 单击注册按钮时打开一个新组件
- reactjs - 图片上传预览:window.URL.createObjectURL() 只工作一次
- java - 空单元格检查规则引擎决策表
- firebase - 将列表视图中的数据打印到 Firebase
- google-bigquery - Jupyter Notebook 无法访问 Big Query
- angular - “HammerInput”类型上不存在属性“maxPointers”
- c - 缺少头文件 (ini.h)
- java - 将列表添加到一组java中
- javascript - 如何使用节点写入 json 文件?