使用 httpClient 和 shareReplay 时如何触发新的 api 请求
How to trigger a new api request when using httpClient & shareReplay
我正在尝试 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;
}
}
组件 1
应请求 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;
});
}
}
组件 2
请求默认 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
ShareReplay 将是有益的,如果您调用了一些元数据(主数据),它不会在组件之间发生变化(cached/sharing 相同的数据)。
要使用新值执行表达式,您需要为请求而不是字段添加 getter。
private get request() {
return this._http.get('https://swapi.dev/api/people/' + this.peopleindex);
}
大多数人使用的调用 httpServices 的模式是这样的。
创建一个单独的服务来调用 rest 端点(围绕 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 link。
我建议为这种情况创建 API 商店。
第一次它将存储 API 具有要存储的特定 ID 和 return 初始调用。
第二次需要存储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()
通过使用以下配置在多个组件之间请求我的 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;
}
}
组件 1
应请求 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;
});
}
}
组件 2
请求默认 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
ShareReplay 将是有益的,如果您调用了一些元数据(主数据),它不会在组件之间发生变化(cached/sharing 相同的数据)。
要使用新值执行表达式,您需要为请求而不是字段添加 getter。
private get request() {
return this._http.get('https://swapi.dev/api/people/' + this.peopleindex);
}
大多数人使用的调用 httpServices 的模式是这样的。
创建一个单独的服务来调用 rest 端点(围绕 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 link。
我建议为这种情况创建 API 商店。
第一次它将存储 API 具有要存储的特定 ID 和 return 初始调用。
第二次需要存储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);
}
}