【问题标题】:Which rxjs operator should i use for the following condition?对于以下情况,我应该使用哪个 rxjs 运算符?
【发布时间】:2021-01-31 21:10:55
【问题描述】:

如果外部 observable 给出有效值,我有以下代码运行内部 observable..

  1. 这里的第一个可观察对象,即外部可观察对象,是一个behaviorSubject。此行为主体的初始值为 null。用户登录后,behaviourSubject 会为我们提供一个用户对象。
  2. 作为内部可观察对象的第二个可观察对象是一个 http 调用,它将完全依赖于用户对象。所以它只会在外部 observable 给我们一个有用的用户对象而不是 null 时运行。
  3. 最后我想订阅内部 observable..

现在我不知道应该使用哪个运营商,所以我在订阅中使用订阅..这是我的代码

item = [];
ngOnInit(){
 this.service.outerObs.subscribe(user => {
  if(user !== null) {
   this.http.get('some route', {headers: new HttpHeader({"Authorization": user.token})})  //here i am using the user object
    .subscriber(result => {
       this.items = result;
     })
  }
 })
}

如果我先登录然后访问这个组件,我不会有任何问题,因为我的 behaviorSubject 将拥有最后一个用户对象。但是,如果我已经在这个组件中并尝试重新加载我的应用程序,那么我就会遇到问题,因为我的 autoLogin 功能需要一些时间才能在 behaviorSubject 中设置用户对象。所以我必须先检查 behaviorSubject 是否有一个有用的用户对象而不是 null发送http调用... 我应该使用哪个 rxjs 运算符来解决这个问题?

【问题讨论】:

    标签: angular rxjs


    【解决方案1】:

    我建议进行 2 项更改

    1. 您可以将ReplaySubject 与缓冲区1 一起使用,而不是将BehaviorSubject 与默认null 一起使用。它的行为方式与BehaviorSubject 相同,但您不必处理默认值null

    2. 您可以使用像 switchMap 这样的高阶映射运算符从外部可观察到的切换到 HTTP 调用。

    试试下面的

    服务

    @Injectable()
    export class SomeService {
      private outerObsSrc = new ReplaySubject<any>(1); // <-- hold and emit last value on subscription
      public outerObs = this.outerObsSrc.asObservable();
      
      ...
    }
    

    组件

    item = [];
    
    ngOnInit() {
      this.service.outerObs.pipe(
        switchMap(user => {
          if (isValidUserCheck) { // <-- check if the `user` variable is a valid user
            return this.http.get('some route', {headers: new HttpHeader({"Authorization": user.token})});
          }
          return of(null); // <-- return `null` if `user` is invalid
        })
      ).subscribe(
        result => {
          if (!!result) { // <-- check if `result` is defined
            this.items = result
          }
        },
        err => {
          // always good practice to handle HTTP errors
        }
      );
    }
    

    更新:subscribe 重载被弃用

    正如@LarsVanderheydt in their comment 所提到的,订阅重载直接在原始答案中使用发送回调已被弃用。相反,您可以发送一个包含回调的对象。

    ngOnInit() {
      this.service.outerObs.pipe(
        ...
      ).subscribe({
        next: (result) => {
          if (!!result) { // <-- check if `result` is defined
            this.items = result
          }
        },
        error: (err) => {
          // always good practice to handle HTTP errors
        }
      });
    }
    

    【讨论】:

    • 如果你没有对结果做任何事情,你也可以使用过滤器操作符(旁注,在 subscribe 中传递 2 个单独的方法很快就会被弃用。所以习惯于传递一个带有 next 和 error 的对象({ 下一个: () => {}, 错误: () => {}})
    • @LarsVanderheydt:这是关于订阅回调弃用的一个好点。我已经更新了答案。谢谢:)
    猜你喜欢
    • 2021-01-02
    • 1970-01-01
    • 1970-01-01
    • 2016-03-15
    • 1970-01-01
    • 2017-03-13
    • 2011-09-13
    • 2016-02-19
    • 2018-07-06
    相关资源
    最近更新 更多