在 Angular 2 / 4 中使用 Observable 定期使用来自 http 服务的数据

Periodically consume data from http service using Observable in Angular 2 / 4

我正在学习使用 angular (4) 作为我的 REST api 后端的前端。

我目前有一个显示帖子列表的 PostList 组件。我在我的 daoService 中使用返回一个 Observable>,并在我的 PostListComponent 中的 onInit 中订阅它。 这一切都很好,我对此非常满意,但是我想使用类似间隔的东西来自动每隔 5 秒进行一次调用。 我最初尝试遵循在 https://angular.io/docs/ts/latest/tutorial/toh-pt6.html#!#sts=Observables 的官方 angular 站点中看到的一些类似模式,但是用例足够不同并且我的项目结构足够不同以至于我在遵循它时遇到了真正的问题一个有用的方法,最终放弃了。我有很多 google 并且正在努力寻找一种直接的方法来使用 observer/subscriber 模式以一定的间隔定期使用 api 中的数据。

关于我如何调整以下代码以每隔一段时间进行调用的任何建议对我来说都非常有用,而且我想,很多其他开发者都是 angular 的新手。

import { Injectable } from '@angular/core';
import { Http, RequestOptions } from '@angular/http';
import {Post} from '../class/post';
import 'rxjs/add/operator/toPromise';
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable()
export class PostDaoService      {

  private jwt: String;

  private commentsUrl = 'http://MYDOMAIN/posts';

  constructor(private http: Http, private opt: RequestOptions) {
    // tslint:disable-next-line:max-line-length
    this.jwt = 'eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJQYXNjYNFHUHSFWQiOiIxMjMiLCJyb2xlIjoiYWRtaW4ifQ.4D9TUDQAgIWAooyiMN1lV8Y5wVCrIF4rAeGzFzelSE9diqHMik9WE9x4EsNnEcxQXYATjxAZovpp-m72LpFADA';
   }

  getPosts(): Observable<Array<Post>> {
    this.opt.headers.set('Authorization', 'Bearer ' + this.jwt);
    this.opt.headers.set('Content-Type', 'application/json');
    return this.http.get(this.commentsUrl)
      .map((response) => response.json())
      .map((data: any) => {
        return data._embedded.posts as Post[];
      });
  }
}

import { ContextMenuService } from '../../../baseui-module/context-menu/context-menu.service';

import { Post } from '../../class/post';
import { PostDaoService } from '../../service/post-dao.service';
import {Component, Input, OnInit} from '@angular/core';

@Component({
  selector: 'app-post-list',
  templateUrl: './post-list.component.html',
  styleUrls: ['./post-list.component.css']
})
export class PostListComponent implements OnInit {

  posts: Post[];

  constructor(public service: ContextMenuService, public dao: PostDaoService) { }

  ngOnInit() {
    this.service.postItems();
    this.dao.getPosts().subscribe((data: Array<Post>) => {
      this.posts = data;
    });
  }

  public getItems(): Post[] {
    return this.posts;
  }
}

诀窍是使用 mergeMap/flatMap(取决于您的 rxjs 版本):

getPosts(trigger: Observable<any>): Observable<Array<Post>> {
  this.opt.headers.set('Authorization', 'Bearer ' + this.jwt);
  this.opt.headers.set('Content-Type', 'application/json');
  return trigger.flatMap(() =>
     this.http.get(this.commentsUrl)
      .map((response) => response.json())
      .map((data: any) => {
        return data._embedded.posts as Post[];
      });
}

然后在你的组件中:

this.dao.getPosts(Observable.timerInterval(0, 5000)
   .subscribe(data => ....);

显然您可以将它与其他触发器一起使用:

this.dao.getPosts(Observable.fromEvent(refreshButton, 'click'))

点击刷新按钮时刷新

顺便说一句,您可能希望避免订阅,而是定义:

this.posts$ = this.dao.getPosts(...);

并在您的模板中:

<any *ngFor="let post of posts$">post display here</any>

这会更有效并降低悬空订阅者和内存泄漏的风险。