Rxjs 发送请求一次

Rxjs 发送请求一次,rxjs,observable,angular6,Rxjs,Observable,Angular6,请帮忙解决这个问题 我有一个服务方法 public list(): Observable<ILanguage[]> { return Observable.create((observer: Observer<ILanguage[]>) => { if (this._languages && this._languages.length > 0) { observer.ne

请帮忙解决这个问题

我有一个服务方法

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():可观察{
返回可观察的。创建((观察者:观察者)=>{
if(this.\u languages&&this.\u languages.length>0){
观察者:下一步(本章);
observer.complete();
}否则{
this._http.get(this._constants.apirl+'/langs').subscribe((所有语言:ILanguage[])=>{
这是。_语言=所有语言;
观察者:下一步(本章);
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();
                });
            }
        });
    }
public list():可观察{
返回可观察的。创建((观察者:观察者)=>{
if(this.\u languages&&this.\u languages.length>0){
观察者:下一步(本章);
observer.complete();
}否则,如果(!this.\u请求发送){
这是.\u requestIsSend=true;
this._http.get(this._constants.apirl+'/langs').subscribe((所有语言:ILanguage[])=>{
这是。_语言=所有语言;
观察者:下一步(本章);
observer.complete();
});
}
});
}

您的问题有点神秘,但我认为您要问的是如何防止重复调用HTTP API。在第一次HTTP调用完成之前,您可能已经在您的
list()
observable上订阅了多次。您的标志仅在第一次调用完成后阻止API调用,从而导致不必要的同时调用

但别担心。这种缓存要求已经内置到RxJS中,并且带有
ReplaySubject
,因此您不需要自己实现它
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$;
}

我们在共享函数的可观测值方面有两个问题:
-每个函数调用都返回新的可观察值(记忆函数)
-可观测is(将可观测转换为热)

import*as_memoize from'lodash/memoize';
从“rxjs/operators”导入{shareReplay};
导出函数ShareReplayObservable(目标、键、描述符){
const originalMethod=descriptor.value;
const getobservefn=函数(…参数){
返回originalMethod.apply(this,args.pipe)(shareReplay());
};
descriptor.value=\u memoize(getobservefn);
返回描述符;
}
@ShareReplayObservable
public list():可观察{
返回此;
}

您可以直接使用指定1作为参数的
take
方法,当您的问题不清楚时,该方法将立即执行,服务何时出错?您能举个例子吗?当一个服务方法调用与多个位置同时发生时,该方法无法正常工作。这不是代码。不是与相同的框架。
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$;
}
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');
    }