Angular 6 发送请求一次



请帮忙解决问题

我有一个服务方法

public list(): Observable<ILanguage[]> {
return Observable.create((observer: Observer<ILanguage[]>) => {
if (this._languages && this._languages.length > 0) {
observer.next(this._languages);
observer.complete();
} else {
this._http.get<ILanguage[]>(this._constants.apiUrl + '/langs').subscribe((allLanguages: ILanguage[]) => {
this._languages = allLanguages;
observer.next(this._languages);
observer.complete();
});
}
});
}

如果方法调用发生延迟 - 一切正常,请求发送一次

但是,如果几乎同时调用该方法 - 有几个请求

尝试放置引导标志,这也不起作用

public list(): Observable<ILanguage[]> {
return Observable.create((observer: Observer<ILanguage[]>) => {
if (this._languages && this._languages.length > 0) {
observer.next(this._languages);
observer.complete();
} else if (!this._requestIsSend) {
this._requestIsSend = true;
this._http.get<ILanguage[]>(this._constants.apiUrl + '/langs').subscribe((allLanguages: ILanguage[]) => {
this._languages = allLanguages;
observer.next(this._languages);
observer.complete();
});
}
});
}

你的问题有点晦涩难懂,但我认为你要问的是如何防止重复调用你的HTTP API。在第一个 HTTP 调用完成之前,您可能在可观察list()上多次订阅。您的标志仅在第一次调用完成后阻止 API 调用,从而导致不需要的同时调用。

但不要担心。这种缓存要求已经内置到 RxJSReplaySubject中,因此您无需自行实现。ReplaySubject采用单个参数,即订阅时应向所有订阅者发出的最后一个值的数量。只需使用1作为参数值,它将缓存您的可观察量的最新值(我猜都是语言(

您的代码可以简化为:

private languages$: Observable;
public list(): Observable<ILanguage[]> {
if (!this.languages$) {
this.languages$ = new ReplaySubject(1);
this._http.get<ILanguage[]>(this._constants.apiUrl + '/langs').subscribe((allLanguages: ILanguage[]) => {
this.languages$.next(allLanguages);
});
}
return this.languages$;
}

甚至还有一种涉及管道的更清洁、更不那么迫切的解决方案。有一个管道用于与多播主体共享可观察的排放。对于缓存,您可以使用shareReplay(1)管道,其行为与ReplaySubject(1)完全相同。因此,您可以创建一个可连接的可观察对象(这对您来说可能不是必需的(。要从中创建普通的可观察量,只需将其管道传输到refCount()。结果是,如上所述,一个可观察量,它将最后一个缓存值重新发送到后期订阅者。

private languages$: Observable;
public list(): Observable<ILanguage[]> {
if (!this.languages$)
this.languages$ =
this._http.get<ILanguage[]>(this._constants.apiUrl + '/langs')
.pipe(shareReplay(1))
.pipe(refCount());
return this.languages$;
}

我们在从函数共享可观察性方面有 2 个问题:
- 每个函数调用返回新的可观察(记住函数(- 可观察是冷的(将可观察转换为热(

import * as _memoize from 'lodash/memoize';
import { shareReplay } from 'rxjs/operators';
export function ShareReplayObservable(target, key, descriptor) {
const originalMethod = descriptor.value;
const getObservableFn = function (...args) {
return originalMethod.apply(this, args).pipe(shareReplay());
};
descriptor.value = _memoize(getObservableFn);
return descriptor;
}

@ShareReplayObservable
public list(): Observable<ILanguage[]> {
return this._http.get<ILanguage[]>(this._constants.apiUrl + '/langs');
}

最新更新