繁体   English   中英

角度RXJS结构可观察

[英]Angular RXJS structuring observables

我有一个FeatureToggle守护程序,该函数调用FeatureToggle服务以获取一系列功能切换,但我一直在努力寻找如何构造可观察对象的方法,类似于我对诺言所做的操作。

守卫-

canActivate() {
   if(this.toggleService.hasToggles){
      return this.toggleService.isOn('my toggle');
   } else {
      return this.toggleService.getToggles().subscribe(() => {
         return this.toggleService.isOn('my toggle')
      })
   }
}

服务-

@Injectable    
export class ToggleService {
       private _toggles: string[];
       private _hasToggles: boolean;

       getToggles() {
          return this.http.get('...').subscribe((toggles) => {
             this._toggles = toggles;
          })
       }

       isOn(toggle) {
          // return if toggle is in this._toggles;
       }
    }

但是,由于我已经在该服务内部进行预订,因此我将返回的是订阅,而不是可观察的。 我可以在getToggles创建对observable的本地引用,并返回该引用,但这是我应该使用的模式吗?

您可以使用ReplaySubject重复上次发射值新的订阅,然后有getToggles()调用http.get()只有一次。

https://www.learnrxjs.io/subjects/replaysubject.html

@Injectable({providedIn: 'root'})
export class ToggleService {
    private _toggles: ReplaySubject<string[]>;

    getToggles(): ReplaySubject<string[]> {
        if (!this._toggles) {
            this._toggles = new ReplaySubject();
            this.http.get('...').subscribe((toggles) => this._toggles.next(toggles));
        }
        return this._toggles;
    }

    isOn(toggle): Observable<boolean> {
        return this.getToggles().pipe(map(toggles => toggles.includes(toggle)));
    }
}

您还可以使用shareReply运算符:

https://www.learnrxjs.io/operators/multicasting/sharereplay.html

@Injectable({providedIn: 'root'})
export class ToggleService {
    private _toggles: Observable<string[]>;

    getToggles(): Observable<string[]> {
        if (!this._toggles) {
            this._toggles = this.http.get('...').pipe(shareReplay(1));
        }
        return this._toggles;
    }

    isOn(toggle): Observable<boolean> {
        return this.getToggles().pipe(map(toggles => toggles.includes(toggle)));
    }
}

使用Observable时,总是存在无法再传递Observable的边缘。 在Angular中,它们可以传递到视图模板中,并通过| async订阅| async | async管道。 或者,在您的情况下,作为canActivate的返回值。 因此,在您的服务中使用Observables非常方便。

在服务中,如果要缓存结果,可以使用BehaviourSubject存储它们,然后将它们作为Observable传递给其他对象。 或者,您可以使用shareReplay运算符创建一个可观察shareReplay并重新使用它。 或者,简单地,您可以将它们存储起来并使用'rxjs'of函数将其返回。 我将说明最后一个选项。

@Injectable    
export class ToggleService {
   private _toggles: string[];
   private _hasToggles: boolean;

   getToggles(refresh?: boolean) {
      if (!refresh || !this.toggles) {
      return this.http.get('...').pipe(
        tap((toggles) => {
         this._toggles = toggles;
        });
      );
      } else {
        return of(this._toggles);
      }

   }

isOn您还可以返回boolean类型的Observable 这样,您就可以尽可能地传递它。

   isOn(toggle): Observable<boolean> {
      return this.getToggles().pipe(
        map(toggles => toggles.includes(toggle))
      )
   }

canActivate变得非常简单:

canActivate(): Observable<boolean> {
  return this.toggleService.isOn('my toggle');
}

Angular订阅返回的observable。 无需检查是否已加载切换开关-该服务已经解决了这一问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM