【问题标题】:How to make an http call every 2 minutes with RXJS?如何使用 RXJS 每 2 分钟进行一次 http 调用?
【发布时间】:2017-06-28 17:37:33
【问题描述】:

我有一项服务会每 2 分钟调用一次我的休息服务。在我的服务中,我有以下功能

  getNotifications(token: string) {
     const body = 'xxxxxxxxx=' + token;
     return this.http.post('/rest/ssss/ddddddd/notificationcount', body, this.options)
          .map((res) => res.json());
  }

在我的组件上,我调用我的服务函数来调用 API。

this.notificationService.getNotifications(this.token).subscribe((data) => {
  console.log(data);
});

我想每 2 分钟打一次电话,最好的方法是什么?

【问题讨论】:

  • 你看repeatWhen了吗?

标签: angular rxjs angular-http


【解决方案1】:

既然你已经在使用Observables,那就好好利用吧:)Obersvable.interval()是你这里的好朋友:

在您的组件中,执行以下操作:

Observable
    .interval(2*60*1000)
    .timeInterval()
    .mergeMap(() => this.notificationService.getNotifications(this.token))
    .subscribe(data => {
        console.log(data);
    });

解释:

  1. .interval() 创建一个每 2 次发出一个事件的 observable 分钟。
  2. .timeInterval() 将发出项目的 Observable 转换为一个 发出指示之间经过的时间量 排放。
  3. .mergeMap() 然后包装您的每一个服务调用, 将结果转换为 observable 并返回。这确保 调用您在第 0、第 2、第 4、第 6 分钟的服务呼叫 同步。 (想想有很多.then()),即第2分钟的服务只有在第0分钟的调用之后才会被调用,4th只会在第2分钟之后被调用,以此类推。
  4. .subscribe()终于可以订阅数据了

更新:

如果您使用可管道操作符(rxjs5 及更高版本),只需管道操作符而不是链接它们:

interval(2 * 60 * 1000)
    .pipe(
        mergeMap(() => this.notificationService.getNotifications(this.token))
    )
    .subscribe(data => console.log(data))

【讨论】:

  • 我遇到过与此问题中描述的案例类似的案例。由于我是 Angular 的新手,我需要知道的是这些数据是否可以动态呈现到页面。假设这个数据是一个对象数组,我在一个表上遍历它们,这个表会每 2 分钟用服务返回的“新”数据更新一次吗?
  • @jkonst 是的。它会的,只要你正确绑定数据
  • @jkonst 你可以通过使用 Angular 5 中的异步管道来做到这一点
  • @rotemx 是的,这是另一种方法。这样data不需要是对象数组而是observable本身,所以需要修改上面的代码。
【解决方案2】:

如果你使用的是 rxJs 6+,你可以简单地使用间隔方法来做。像这样-

import { interval } from 'rxjs';

interval(3000).subscribe(x => /* do something */)

【讨论】:

    【解决方案3】:

    如果您不想进行 http 调用,而只想在 2 分钟后做某事,那么您可以执行以下操作。

     Observable.interval(2*60*1000)
      .subscribe(() => {
        // do something.
        // or callSomeMethod();
      });
    

    如果您使用的是 rxjs 6+,那么您可以这样做:

      interval(2*60*1000)
      .subscribe(() => {
        // do something.
        // or callSomeMethod();
      });
    

    还有一件更重要的事情你想做,你应该在离开当前页面后销毁这个 observable,因为你不希望在实际上不需要这些额外的计算时在幕后进行。

    有多个选项可以取消订阅这个 observable。

    1. 您应该保存对 observable 的引用并在 onDestroy 方法中取消订阅。

       this.observableRef = Observable.interval(60000)
       .subscribe(() => {
         // do something
        });
      
       // call this method in OnDestroy method of the page.
       this.observableRef.unsubscribe();
      
    2. 或使用ngx-take-until-destroy

       Observable.interval(60000)
       .takeUntil(this.destroyed$)
       .subscribe(() => {
         //  do something
       });
      

    【讨论】:

      【解决方案4】:

      我有类似的需求。可能对某人有用,因此在这里写它。我的 Angular 版本是 9.1.5。 我正在检查用户是否已登录并每 10 分钟发送一次 http 请求,直到用户进入该组件。

       const secondsCounter = interval(60000); //Refreshes every 10 minutes
       secondsCounter
       .pipe(
         tap(console.log),
         takeWhile(x => this.notificationService.isLoggedIn()),
         flatMap(() => this.notificationService.getNotifications(this.token))
       ).subscribe()
      

      【讨论】:

        【解决方案5】:

        执行时间限制和按结果手动停止的小示例

        this.insalesXlsSubject.pipe(
          switchMap((job_id: string) => {
            return interval(1000).pipe(
              mergeMap((i) => {
                return this.http.get(`${environment.backend}/${this.route.snapshot.params.insales_app_name}/api/make_insales_xls?job_id=${job_id}`)
              }),
              tap((y: any) => {
                if (y.status == 'finished') {
                  this.insalesXlsStatusSubject.next()
                }
              }),
              takeUntil(race([
                this.insalesXlsStatusSubject,
                timer(60 * 1000).pipe(
                  takeUntil(
                    this.insalesXlsStatusSubject
                  )
                )
              ]))
            )
          })
        ).subscribe()
        

        【讨论】:

          【解决方案6】:
          import {Observable} from 'rxjs/Rx';
          
            Observable.interval(2 * 60 * 1000).subscribe(x => {
              callyourmethod();
            });
          

          评论后更新

          this.interval = setInterval(() => {
                  this.yourservicecallmethod();
              }, 2 * 60 * 1000);
          

          【讨论】:

          • 大概他想要一个每两分钟发出一个新 HTTP 响应的 observable。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-11-15
          • 2020-09-30
          • 2018-05-11
          • 2015-07-31
          • 2014-12-21
          • 1970-01-01
          相关资源
          最近更新 更多