如何在使用 httpClient 和 shareReplay 时触发新的 api 请求



我试图通过使用以下配置在多个组件之间sharereplay()我的httpClient请求:

apicaller.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
// import rxjs map
import { map, shareReplay } from 'rxjs/operators';
@Injectable({
providedIn: 'root',
})
export class ApicallerService {
peopleindex: number = 1;
constructor(private _http: HttpClient) {}
private readonly request = this._http
.get('https://swapi.dev/api/people/' + this.peopleindex)
.pipe(shareReplay());
getData(peopleindex: number = 1) {
this.peopleindex = peopleindex;
return this.request;
}
}

Component1

应该请求api获取id 2的详细信息

import { Component, OnInit } from '@angular/core';
import { ApicallerService } from '../apicaller.service';
@Component({
selector: 'app-component1',
templateUrl: './component1.component.html',
styleUrls: ['./component1.component.css'],
})
export class Component1Component implements OnInit {
apiresponse: any;
editRes: any;
constructor(private _apicaller: ApicallerService) {}
ngOnInit(): void {
this._apicaller.getData(2).subscribe((data: any[]) => { // <-- Notice 2 in the argument
console.log(data);
this.apiresponse = data;
});
}
}

于Component2

请求默认id

import { Component, OnInit } from '@angular/core';
import { ApicallerService } from '../apicaller.service';
@Component({
selector: 'app-component2',
templateUrl: './component2.component.html',
styleUrls: ['./component2.component.css']
})
export class Component2Component implements OnInit {
apiresponse: any = {};
constructor(
private _apicaller: ApicallerService
) { }
ngOnInit(): void {
// get data from api using service
this._apicaller.getData().subscribe(
(data) => {
this.apiresponse = data;
}
);
}
}

但是,component1

没有发出peopleindex = 2

的新请求。要复制,可以使用我的stackblitz设置:https://stackblitz.com/edit/angular-ivy-gdxyy6?file=src%2Fapp%2Fcomponent1%2Fcomponent1.component.ts

我建议为这种情况创建API存储

  • 第一次,它将存储API与特定的id来存储和返回初始调用。

  • 第二次调用存储的API

export class ApicallerService {
apiStore = new Map();
constructor(private _http: HttpClient) {}
private getApiRequest(id) {
return this._http.get('https://swapi.dev/api/people/' + id).pipe(shareReplay());
}
getData(peopleindex: number = 1) {
if (!this.apiStore.has(peopleindex)) {
this.apiStore.set(peopleindex, this.getApiRequest(peopleindex));
}
return this.apiStore.get(peopleindex);
}
}

ShareReplay将是有益的,如果你调用一些元数据(主数据),这将不会在组件之间改变(缓存/共享相同的数据)。

要用新值执行表达式,你需要为request而不是field添加getter。

private get request() { 
return this._http.get('https://swapi.dev/api/people/' + this.peopleindex);
}

大多数人调用httpServices的模式是这样的:

创建一个单独的服务来调用其他端点(httpClient的包装)。

@Injectable({
providedIn: 'root',
})
export class ApiService {
constructor(private _http: HttpClient) {}
get(url: string) {
return this._http
.get(url);
}
post(url: string, data) {
return this._http
.post(url, data);
}
}

然后添加依赖于apiService的特性服务。

@Injectable({
providedIn: 'root',
})
export class PeopleService {
constructor(private _api: ApiService) {}
getData(peopleindex: number = 1) {
console.log(peopleindex);
return this._api
.get('https://swapi.dev/api/people/' + peopleindex);
}
}

从你的特性组件中调用这些特性服务。

export class Component1Component implements OnInit {
apiresponse: any;
editRes: any;
constructor(private _peopleService: PeopleService) {}
ngOnInit(): void {
this._peopleService.getData(2).subscribe((data: any[]) => {
this.apiresponse = data;
});
}
}
export class Component2Component implements OnInit {
apiresponse: any = {};
constructor(
private _peopleService: PeopleService
) { }
ngOnInit(): void {
// get data from api using service
this._peopleService.getData().subscribe(
(data) => {
console.log(data);
this.apiresponse = data;
}
);        
}
}

这里是相同的stackblitz链接。

最新更新