如何存储或缓存局部变量,以便可以在整个应用程序中共享API调用的结果?
我有以下Angular 6模块,该模块基本上创建了一个提到指令,以便能够执行许多应用程序中流行的@提及:
@NgModule({
imports: [
CommonModule
],
exports: [
MentionDirective,
MentionListComponent
],
entryComponents: [
MentionListComponent
],
declarations: [
MentionDirective,
MentionListComponent
]
})
export class MentionModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: MentionModule
};
}
}
这是实际的指令:
export class MentionDirective implements OnInit, OnChanges {
items: any[];
constructor(
public autocompletePhrasesService: AutocompletePhrasesService
) { }
ngOnInit() {
this.autocompletePhrasesService.getAll()
.pipe(first())
.subscribe(
result => {
this.items = result;
},
() => { });
该指令在我的核心模块中调用一个函数来检索数据:
export class AutocompletePhrasesService {
public autoCompletePhrases: string[];
constructor(private http: HttpClient) { }
getAll(): Observable<string[]> {
return this.http.get<string[]>(this.baseUrl + '/getall');
}
我的问题是,此指令在单个页面上可能有20-30个实例,并且该指令的每个实例都会调用API。如何更改代码,以便每个应用程序实例仅调用一次API?
数据通常不会从API更改。
我尝试将服务的结果存储在公共autoCompletePhrases变量中,并且仅在它为空但没有用时才调用它
答案 0 :(得分:1)
您想要一些类似“缓存”的内容。它易于维护,让人喜欢
data:any;
getData()
{
if (!this.data)
return this.httpClient.get(....).pipe(
tap(result=>{
this.data=result
}))
return of(this.data)
}
当您订阅“ getData”时,可能会发生两件事:this.data具有值,然后返回具有可观察性的数据。或此数据没有值,然后返回get并将结果存储在data中-tap在subscription-之后执行。因此,您始终订阅“ getData”,但是该服务仅在没有数据的情况下才调用API(注意:一次可能会发生一次调用,而对API会多次调用)
答案 1 :(得分:1)
以下是一些AngularJS / TypeScript代码,以演示如何处理此问题的逻辑。抱歉,但我没有时间将其转换为Angular。我确实相信那里也有可以更完整地处理缓存的软件包,但这是手动的方式:)
private printerList: SelectItem[] = [];
private printerPromises: IDeferred<SelectItem[]>[] = [];
private printersLoading: boolean = false;
private printersLoaded: boolean = false;
public getPDFPrinterList(): ng.IPromise<SelectItem[]> {
let defer: IDeferred<SelectItem[]> = this.$q.defer<SelectItem[]>();
this.printerPromises.push(defer);
if (this.printersLoading) {
return defer.promise;
}
if (this.printersLoaded) {
for (let i = 0; i < this.printerPromises.length; i++) {
this.printerPromises[i].resolve(this.printerList);
}
this.printerPromises = [];
} else {
this.printersLoading = true;
this.$http.get<SelectItem[]>(this.printerListUrl, { cache: false }).then((response: ng.IHttpResponse<SelectItem[]>) => {
if (response.data) {
this.printerList = response.data;
for (let i = 0; i < this.printerPromises.length; i++) {
this.printerPromises[i].resolve(this.printerList);
}
this.printerPromises = [];
this.printersLoaded = true;
} else {
console.log('Server Error Obtaining Printer List');
for (let i = 0; i < this.printerPromises.length; i++) {
this.printerPromises[i].reject('Server Error');
}
this.printerPromises = [];
}
this.printersLoading = false;
}, (response: ng.IHttpResponse<any>) => {
if (response.data) {
console.log(response.data.Message ? response.data.Message : response.data);
}
for (let i = 0; i < this.printerPromises.length; i++) {
this.printerPromises[i].reject('Server Error');
}
this.printerPromises = [];
});
}
return defer.promise;
}