Angular - 可能的竞争条件 - `publish().refCount()`?

Angular - Possible Race Condition with - `publish().refCount()`?

我读过 article,其中显示了 3 个异步订阅 HTTP 请求的示例。

@Component({
  selector: 'my-app',
  template: `
    <div>
      <p>{{ (person | async)?.id   }}</p>
      <p>{{ (person | async)?.title   }}</p>
      <p>{{ (person | async)?.body   }}</p>
    </div>
  `,
})
export class App {
  constructor(public http: Http) {
    this.person = this.http.get('https://jsonplaceholder.typicode.com/posts/1')
     .map(res => res.json())
  }
}

我已经知道这里不需要异步,可以使用ReplaySubject,还有很多其他解决方案,但这不是我所追求的。

作者说:

The current solution that people suggest:

this.http.get('https://jsonplaceholder.typicode.com/posts/1') .map(res => res.json()).share() ( which is publish().refCount().)

问题:

但重新考虑 publish().refCount() - 是否有可能(出于某种原因):

换句话说 -

sub1 导致 refcount()=1(调用 http)。但与此同时 sub2(第二次订阅)已完成:

  sub1 ———————A—————> http invoked    
   <—————————B———————response

查看 A & B 个阶段:

refcount()什么时候会是2?它是在 A 阶段(before/while http 执行)还是在 B 阶段的订阅也将被视为 refcount()=2

这确实是一个有趣的问题。但我认为这段代码中没有涉及竞争条件。

事实是,所有订阅都是在模板中使用 async 函数同步完成的。 这意味着,当第一个订阅确实完成时,请求将被触发,但如果服务器在所有其他订阅完成之前响应(如果可能的话),那么主线程将被占用,因此不会触发另一个请求当下一个 subscribe 到达时。

这是我制作的一个小示例,它试图重现该用例。

const timer = Rx.Observable.of("value")
  .do(() => console.log("start request"))
  .delay(1)
  .do(() => console.log("end request"))
  .publish().refCount()

console.time("sub");
for (var i=0; i < 10; i++) {
  console.log("subscribe" + i)
  timer.subscribe()
}
console.timeEnd("sub")
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>

这里我模拟了一个服务器在 1ms 中响应的请求,但所有订阅(至少在我的计算机上)需要大约 10ms 才能完成。所以你可以说响应在订阅完成之前到达。

如您在日志中所见,请求仅被触发一次:)