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

时间:2017-07-01 16:40:26

标签: javascript angular rxjs5

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

@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并且还有许多其他解决方案,但这不是我想要的。

作者说:

  

人们建议的当前解决方案:

     

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

问题:

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

  • 第一个(person | async)已经执行了请求(refcount = 1)并且响应在<!>之前返回最后两个(person | async)订阅了? - 这会导致另一个http请求?我的意思是 - 谁保证3个订阅将同时可用以便它们共享相同的结果?竞争条件有可能吗? 因为我听说refcount()受竞争条件限制。

  • 此外,什么时候被认为是“refcount()>0”?当http 被调用时检查该值,还是在响应到达时检查它?

换句话说 -

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

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

关注A&amp; B阶段:

refcount()何时2?它是在舞台A上(在执行http之前/期间)还是在B阶段订阅也会被视为refcount()=2

1 个答案:

答案 0 :(得分:1)

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

问题是,所有订阅都在{{1>}功能的模板中以同步完成。 这意味着,当第一次订阅确实完成时,将触发请求,但是如果服务器在所有其他订阅完成之前响应(如果甚至可能),那么主线程将被占用因此不会触发另一个请求当下一个async到达时。

这是我尝试重现该用例的一个小例子。

&#13;
&#13;
subscribe
&#13;
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")
&#13;
&#13;
&#13;

这里我模拟服务器在<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>中响应的请求,但所有订阅(至少在我的计算机上)都在1ms左右完成。所以你可以说在订阅完成之前响应就到了。

正如您在日志中看到的那样,请求只被触发一次:)