angular - ionic 2 中带有异步管道的重复 http 请求

标签 angular typescript ionic2 rxjs ionic3

我是 ionic 2 的新手。我使用的是 ionic v3.6.1。

请注意 http 请求被触发了 x 次,其中 x 是绑定(bind)到使用异步管道发布的请求。 因此,在这种情况下,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);
  }

html

{{ (post | async)?.id }}
{{ (post | async)?.title}}
{{ (post | async)?.content}}

最佳答案

share() 运算符

每次你订阅一个冷的Observable,它都会被执行。避免这种行为的一种方法是使其变热。您可以使用 .share()operator 执行此操作(这是 .publish().refCount() 的简写,有关这些运算符的更多信息,请参阅进一步内容):

Returns a new Observable that multicasts (shares) the original Observable. As long as there is at least one Subscriber this Observable will be subscribed and emitting data. When all subscribers have unsubscribed it will unsubscribe from the source Observable. Because the Observable is multicasting it makes the stream hot. This is an alias for .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 运算符(单独)是不够的,因为发布了帖子,所以 ngIf 条件变为真,但是子异步管道订阅了一个已经发出其值的 Observable。基本上它呈现这样的东西:

myPostID
<div></div>

有两种方法可以解决这种情况:

  1. .publishReplay(n) :此运算符将重播 Observable 发出的最后 n 个项目。我们将此运算符与 refCount() 相结合,后者将跟踪订阅者的数量并在没有更多订阅者时重置冷可观察对象。

    this.post = this.data.getPostById(this.postId).publishReplay(1).refCount();
    
  2. 使用 *ngIf="post |async as myPost" 这种语法是在 angular 4(或者可能是 4.1,我不记得了)中引入的,它允许你存储结果局部变量 myPost 中的管道。 explainations here .所以你可以将 .share() 部分保留在你的 ts 代码中并最终得到这样一个模板:

    {{ (post | async)?.id }}
    <div *ngIf="post|async as myPost">
        {{ myPost.title}}
        {{ myPost.content}}
    </div>
    

关于 publish()refCount() 的 2 个词:

publish() 将常规 Observable 转换为 ConnectableObservable。这种 Observable 在其 connect() 方法被调用时就开始发射数据(它使 observable 变热)。

来自 the docs :

Rx.Observable.prototype.publish([selector])

Returns an observable sequence that is the result of invoking the selector on a connectable observable sequence that shares a single subscription to the underlying sequence.

refCount()ConnectableObservable上可用的方法,它的作用是在第一次订阅时调用connect()方法.如果所有订阅者取消订阅,然后另一个订阅者要求订阅,它将再次调用。

来自 the docs :

ConnectableObservable.prototype.refCount()

Returns an observable sequence that stays connected to the source as long as there is at least one subscription to the observable sequence.

关于angular - ionic 2 中带有异步管道的重复 http 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46170509/

相关文章:

javascript - 将 FormArray 转换为数组 Angular

typescript - 使用 TypeScript 导入 'global' 模块

javascript - 使变量在回调函数外部可见 - Ionic2

Wordpress API : Get posts from private wordpress. 网站

angular - 在服务中使用 observables 测试错误案例

angular - Webpack - 如何在运行时包含简单的配置文件?

angular - 失败 : Template parse errors: Angular 2

angular - 在 Angular Google Map 中应该有多个标记时只显示一个标记

javascript - 带有分页 : no rows displayed 的 AngularJS ng 表

html - CSS 高级三按钮行格式化