【问题标题】:RxJs - (why) Does an Observable emit it's latest value on a new subsription?RxJs - (为什么)Observable 是否在新订阅中发出它的最新值?
【发布时间】:2017-01-29 19:40:45
【问题描述】:

好的,这是一个快速的,我已经有点筋疲力尽并且让自己感到困惑:D

我正在使用 angular2 和 RxJS Observables。

我有一个带有属性“data”的服务,它是一个在构造函数中设置的 Observable,以及一个返回这个 observable 以订阅的方法。

export class test{
    private data: Observable<Object>
    constructor(private http: Http){
       this.data = this.http.get(url).map( res => res.json());
    }  
    getData(): Observable<Object>{
       return this.data
    }
}

我前段时间曾使用 replaySubjects 来始终将序列的所有值发送给新订阅者。然而,Observable 上面的代码似乎向新订阅者发出了它的最新价值。这是故意的吗?

test(i: number) {
      if (i > 0) {
        setTimeout( () => {
          this.dataService.getData().subscribe( (data) => {
            this.debug.log(data);
            this.test(i-1);
          });
        }, 2000);
      }
    }
test(4)

每次迭代我都会得到一个值。我很困惑,因为一年前当我想要这种行为时,订阅“太晚了”时我没有得到新的价值观。 本质上,我只想缓存 http.get 的结果,并向所有订阅者提供相同的值,而不是为每个订阅发出新的 http 请求(在 getData() 中返回 http.get(url)..)

【问题讨论】:

  • this.http.get(url).map( res =&gt; res.json()).share() 做你想做的事吗?
  • 我很困惑。您说观察者正在为新订阅者发出最后一个值,您似乎不喜欢。然后你说这就是你想要的。这是什么?
  • 对不起,在电话里很累......是的,它的行为符合我的要求。我只是不确定它是否是有意的,因为一年前它并没有那样工作(或者至少我认为)。我想我应该在以后有时间的时候再次阅读 observables

标签: javascript angular rxjs observable


【解决方案1】:

我知道这个问题有点老了,但在我看来答案很混乱。

从 getData() 方法返回的 Observable 就是这样,一个 Observable。所以每次消费者订阅它都会得到响应。所以它工作正常,但它确实每次都发出新请求。

为了缓存结果,有很多方法可以根据您想要的行为来实现。如果只缓存单个请求,我建议不要使用 #publishBehavior 运算符:

export class test{
  private data: Observable<Object>;
  constructor(private http: Http){
    this.data = this.http.get(url)
      .map(res => res.json())
      .publishBehavior([])
      .refCount();
  }  
  getData(): Observable<Object>{
    return this.data;
  }
}

传递给 publishBehavior 的参数是初始值。使用这两个运算符,将在第一个订阅者到达时发出请求。下一个订阅者将获得缓存的答案。

在其他答案中建议使用主题。 publishBehavior 在后台使用主题。但是直接调用 next() 被认为是不好的做法,除非没有其他补救措施,在我看来,这种情况并非如此。即使您直接使用 Subjects,明智的做法是使用 #asObservable() 运算符将 Observable 返回给组件,这样组件就无法访问 next、error 和 complete 方法。

【讨论】:

    【解决方案2】:

    没有。您需要为此使用Subject。它有一个 next() 方法,您可以将新到达的属性发送到该方法,以便将其推送给订阅者。

    除此之外,您还应该创建一个单例服务。每当您的组件在构造函数中实例化它时,它们将接收已由所有数据形成的对象。无需每次都获取数据。

    另外,不要在构造函数中实例化您的数据,而是实现 OnInit 并从那里调用服务器。

    【讨论】:

    • 它是一个服务 (this.dataService.getData()),因为我使用 ng2 DI,所以它在我的应用程序范围内是一个单例。由于该服务没有视图/数据绑定输入,我认为使用构造函数可以吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多