共享运算符是否正常工作?

时间:2018-09-28 05:43:13

标签: rxjs6

这里是一个例子。该来源被认为是半冷半热:

const subject = new Subject()

const source = of(1, 2, 3).pipe(concat(subject))

const hot = source.pipe(
    share()
)

setTimeout(() => {
    hot.subscribe(val => console.log(`a: ${val}`))

    subject.next(6)
}, 1000)

subject.next(4)
subject.next(5)

但是输出:

a: 1
a: 2
a: 3
a: 6

这被认为是预期结果还是错误?

2 个答案:

答案 0 :(得分:1)

是的,这是正确的结果,这就是原因:

  1. 'concat'仅在'of(1,2,3)'完成后才订阅主题。但是由于将hot.subscribe封装在setTimeout中-subject.next(4)和5不会重新发送到热订阅,因为它们在SetTimeout函数中订阅hot之前运行。

  2. of默认情况下具有同步发射,没有延迟,因此您首先从'of'中获得1,2,3,然后从subject.next(6)中获得'6'

  3. 如果在发射和一些订阅者之间存在一些延迟,则使用“共享”是有意义的。

答案 1 :(得分:1)

这是预期的行为。可观察到的是冷的,因为直到第一个订阅者订阅它之后,它才开始产生任何东西,然后它订阅Subject并从主题发出值。时间轴大致是这样:

  1. subject已创建
  2. source已创建
  3. hot已创建
  4. 超时已创建
  5. subject发出4
  6. subject发出5
  7. hot已订阅
  8. hot发出1
  9. hot发出2
  10. hot发出3
  11. hot订阅了subject
  12. subject发出6
  13. hot发出6

定义一个可观察对象只会创建一个可观察对象的蓝图,在您订阅该可观察对象之前,它实际上并不是构建的。这也意味着每次订阅时都会根据该蓝图构建一个新的可观察对象。

share确保在第一个订阅者订阅该观察对象时,它仅构建一次。任何后续的订户将收到已经建立的可观察对象。它们之间是共享

请注意,在订阅之前发出的任何信号都不会重复。构建后,共享的可观察对象很热,因此新订阅将仅接收订阅后发出的事件。

编辑

假设您有一个可观察对象,它每10秒调用一次Web API:

let getFromWebApi = interval(10 * 1000).pipe(
  mergeMap(_ => callWebApi())
)

接下来,假设您想在代码的五个不同位置获得这些结果,您将这样做:

// Somewhere in your code
getFromWebApi.subscribe(response => /* Handle response */);

// Somewhere else in your code
getFromWebApi.subscribe(response => /* Handle response */);

// A third place in your code
getFromWebApi.subscribe(response => /* Handle response */);

// A fourth place in your code
getFromWebApi.subscribe(response => /* Handle response */);

// A fifth place in your code
getFromWebApi.subscribe(response => /* Handle response */);

在五个不同的位置执行此操作将创建五个可观察到的对象,每过10秒就会分别调用一个Web API。如果您每10秒只打一次电话,并且所有订阅都共享响应,这会更好吗?那就是分享让您完成的事情:

let getFromWebApi = interval(10 * 1000).pipe(
  mergeMap(_ => callWebApi()),
  share()
)

// Somewhere in your code
getFromWebApi.subscribe(response => /* Handle response */);
// ^^^ This will create the observable and start making web requests
// every 10 seconds

// The ones below will not create new observables,
// but receive the same observable as above. They will all receive
// responses every 10 seconds when the original observable returns.

// Somewhere else in your code
getFromWebApi.subscribe(response => /* Handle response */);

// A third place in your code
getFromWebApi.subscribe(response => /* Handle response */);

// A fourth place in your code
getFromWebApi.subscribe(response => /* Handle response */);

// A fifth place in your code
getFromWebApi.subscribe(response => /* Handle response */);

如果您查看此JSBin,您会发现订阅source五次,创建了五个“请求”。订阅sharedSource仅创建一个“请求”,