带有异步管道的 ionic 2 中的重复 http 请求
Posted
技术标签:
【中文标题】带有异步管道的 ionic 2 中的重复 http 请求【英文标题】:Duplicated http request in ionic 2 with async pipe 【发布时间】:2018-02-20 13:40:04 【问题描述】:我是 ionic 2 的新手。我正在使用 ionic v3.6.1。
请注意,http 请求被触发 x 次,其中 x 是绑定到使用异步管道发布的请求。 因此,在这种情况下,http 请求被触发了 3 次。
请告知这是最佳做法。
提供者:
getPostById(id: number)
return this.http.get(`$this.rootUrl/$this.posts/$id`).map(res => res.json()).take(1);
ts 文件:
post: Observable<Post>;
ionViewDidLoad()
this.postId = this.navParams.get('postId');
console.log(this.postId);
this.post = this.data.getPostById(this.postId);
(post | async)?.id
(post | async)?.title
(post | async)?.content
【问题讨论】:
【参考方案1】:
share()
运算符
每次订阅冷Observable
时,它都会被执行。避免这种行为的一种方法是让它变热。您可以使用.share()
operator(.publish().refCount()
的简写形式,有关这些运算符的更多信息,请参阅更多信息)来执行此操作:
返回一个多播(共享)原始 Observable 的新 Observable。只要至少有一个订阅者,这个 Observable 就会被订阅并发送数据。当所有订阅者都取消订阅后,它将取消订阅源 Observable。因为 Observable 正在多播,所以它使流变热。这是
.publish().refCount()
的别名。
ionViewDidLoad()
this.postId = this.navParams.get('postId');
console.log(this.postId);
this.post = this.data.getPostById(this.postId).share();
有条件的怪癖
如果您在模板中第一次使用 Observable
,然后在有条件附加的元素 (*ngIf
) 中再次使用它,您可能会遇到一些麻烦,因为 observable 已经运行并且没有将发出新数据。
例如:
模板:
(post | async)?.id
<div *ngIf="post|async">
(post | async)?.title
(post | async)?.content
</div>
ts:
post: Observable<Post>;
ionViewDidLoad()
setTimeout(()=>this.show=true, 5000);
this.postId = this.navParams.get('postId');
console.log(this.postId);
this.post = this.data.getPostById(this.postId).share();
这里share
operator(单独)是不够的,因为发布了帖子,所以 ngIf 条件变为真,但子异步管道订阅了已经发出其值的 Observable。基本上它呈现这样的东西:
myPostID
<div></div>
有两种方法可以解决这种情况:
.publishReplay(n)
:此操作符将重播 Observable 发出的最后 n
th 个项目。我们将此运算符与refCount()
结合使用,它将跟踪订阅者的数量并在没有更多订阅者时重置冷可观察对象。
this.post = this.data.getPostById(this.postId).publishReplay(1).refCount();
使用*ngIf="post |async as myPost"
这个语法是在 Angular 4(或者可能是 4.1,我不记得了)中引入的,它允许您将管道的结果存储在局部变量 myPost
中。 explainations here。所以你可以在你的 ts 代码中保留.share()
part 并最终得到这样一个模板:
(post | async)?.id
<div *ngIf="post|async as myPost">
myPost.title
myPost.content
</div>
关于publish()
和refCount()
的两句话:
publish()
将常规 Observable
转换为 ConnectableObservable
。这种 Observable 在其 connect()
方法被调用后立即开始发送数据(它使 observable 变热)。
来自the docs:
Rx.Observable.prototype.publish([selector])
返回一个可观察序列,该序列是在可连接的可观察序列上调用选择器的结果,该可连接的可观察序列共享对基础序列的单个订阅。
refCount()
是ConnectableObservable
上可用的方法,它的作用是在第一次订阅时调用connect()
方法。如果所有订阅者都取消订阅,然后另一个订阅者请求订阅,则会再次调用它。
来自the docs:
ConnectableObservable.prototype.refCount()
只要至少有一个可观察序列订阅,就会返回一个可观察序列,该序列与源保持连接。
【讨论】:
【参考方案2】:您可以在此处遵循以下模式:
.ts
post: Post;
ionViewDidLoad()
this.postId = this.navParams.get('postId');
console.log(this.postId);
this.data.getPostById(this.postId).subscribe(data =>
this.post= data;
);
模板如下:
.html
post?.id
post?.title
post?.content
【讨论】:
那么在 html 中使用订阅比使用异步管道更可取吗? 现在你有一个问题。首先尝试使用上述方法解决该问题。有很多方法可以做同样的事情。没有人能说这比那个更好,就像那样......所以试试上面的方法,让我们知道你的结果。 顺便说一句 @Sampathpost
不是 Observable<Post>
只是 Post
。
是的,已更正。谢谢,@n00dl3 :)以上是关于带有异步管道的 ionic 2 中的重复 http 请求的主要内容,如果未能解决你的问题,请参考以下文章
在模板中使用带有异步管道的 Observable 时显示加载
带有 ChangeDetectionStrategy.OnPush 和异步管道的 Angular 2 Observable 不起作用
ngFor 块内模板中的异步管道触发 http GET 调用循环