我读过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
和B
阶段:refcount()
什么时候会是2
?是在阶段A
(执行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/[email protected]/dist/global/Rx.js"></script>
在这里,我模拟了服务器在
1ms
中响应的请求,但是所有订阅(至少在我的计算机上)都在10ms
附近完成。因此,您可以说响应是在所有订阅完成之前到达的。如您在日志中所见,该请求仅被触发一次:)