帮助请解决问题
我正在使用一种方法
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();
});
}
});
}
答案 0 :(得分:2)
您的问题有点神秘,但我认为您要问的是如何防止重复调用HTTP API。在第一个HTTP调用结束之前,您可能多次在list()
上进行观察。您的标志仅在第一次调用完成后才阻止API调用,从而导致不必要的同时调用。
但是不用担心。该缓存要求已经通过ReplaySubject
内置在RxJS中,因此您不需要自己实现。 ReplaySubject
采用一个参数,即应在订阅时发送给所有订阅者的最后一个值的数量。只需使用 1 作为参数值,它将缓存您可观察到的最新值(我猜是 allLanguages )
您的代码可以简化为:
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)
完全一样。因此,您创建了一个可连接的可观察对象(is probably not necessary for you)。要从中创建普通的可观察对象,请将其简单地传递到refCount()
。结果是,像上面一样,一个Observables将最新的缓存值重新发布给后期的订户。
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$;
}
答案 1 :(得分:0)
我们在通过函数共享Observable时遇到两个问题:
-每个函数调用都返回新的Observable(记住该函数)
-可观察的是cold(将“可观察的”转换为“热”)
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');
}