【问题标题】:How to implement a polling mechanism in angular which has to be called every interval of time?如何在每个时间间隔都必须调用的角度实现轮询机制?
【发布时间】:2019-05-14 10:33:52
【问题描述】:

如何在Angular中实现轮询机制?

我有一个要订阅的 API 调用,其中包含数据、再次调用它的时间间隔(以毫秒为单位)以及必须停止调用之后的已完成标志。

在第一次调用 API 时, 我们得到结果中的数据, 我们在 result[0].requestInterval 和 我们在 result[0].requestComplete 中获得停止调用 API 的标志 如果是真的,我们必须停止调用API否则再次调用API

this.bookFlightService.GetFlights(this.baseUrl, searchResource, inboundDate)
            .subscribe(result => {
                this.callNo++;
                this.bookFlights = result as BookFlights[];
                this.requestComplete = this.bookFlights[0].complete;
                this.requestInterval = this.bookFlights[0].callAfterMs;
)

【问题讨论】:

    标签: javascript angular angular6 observable angular7


    【解决方案1】:
    destructor$ = new Subject();
    
    this.bookFlightService.GetFlights(this.baseUrl, searchResource, inboundDate).pipe(
      switchMap(response => timer(0, 1000)),
      tap(() => this.callNo++),
      switchMap(() => this.makeHttpCall()),
      takeUntil(this.destructor$),
      tap(response => { if(response.complete) this.destructor$.next(); }),
    ).subscribe(response => console.log(response));
    

    1 - 创建一个主题以在您需要时停止您的直播
    2 - 第一次进行 Http 调用
    3 - 将流更改为计时器(发射一次,然后每给定毫秒)
    4 - 增加您的通话次数(原始代码)
    5 - 再次将您的计时器流切换到您的 API 的新调用
    6 - 直到对象发出 7 - 如果需要,在析构函数上发射

    Demo stackblitz

    【讨论】:

    • 嗨@trichetriche,您的解决方案非常适合一次通话。即当 response[0].complete 在第一次调用中为真时!但是当第一次调用的 response[0].complete 为 false 时,我们会在无限时间里有不可阻挡的 API 命中! :(
    • @SumanKumar 只需反转最后两个运算符(tapswitchMap)。我已经更新了我的答案。
    • 感谢您的回复。还是行不通。即使在 3-4 次调用后 response.complete 为真,我们也有不可阻挡的调用。
    • 我尝试使用 do while 循环。这是一个可怕的想法。我已经改写了这个问题,如果它可能对你有更多帮助?
    • @SumanKumar 抱歉,对我的运营商有点困惑。我已经编辑了我的代码,你可以see it working here.
    【解决方案2】:

    我们可以像这样定期调用我们的服务。

    Observable
        .interval(2*60*1000)
        .timeInterval()
        .flatMap(() => this.bookFlightService.GetFlights(abc, def, ghi)
        .subscribe(data => {
            console.log(data);
        });
    

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

    间隔(2 * 60 * 1000) 。管道( flatMap(() => this.bookFlightService.GetFlights(abc, def, ghi) ) .subscribe(data => console.log(data))


    尝试使用 RxJS 中的计时器:

    import { Subscription, timer, pipe } from 'rjxs';
    import { switchMap } from 'rxjs/operators';
    
    subscription: Subscription;
    statusText: string;
    
    ngOnInit() {
        this.subscription = timer(0, 10000).pipe(
          switchMap(() => this.myservice.checkdata())
        ).subscribe(result => this.statustext = result);
    }
    

    RxJS 的interval(10000) 不合适,因为它只会在 10 秒后才开始发出值,而不是第一次立即发出。

    计时器(0, 10000) 将立即 (0) 和每 10 秒 (10000) 发出值。

    【讨论】:

    • 但是我们的区间也是动态的。它不是一个固定值。我们在 this.requestInterval = this.bookFlights[0].callAfterMs; 中从 API 本身获取间隔
    • 你不应该再使用这种不推荐使用的链接 Observable 方法的方式了。
    • 您可以动态设置间隔值。首先准备好你的间隔值,然后加载这个服务
    • @Jaykant 而如何停止?我们还从 API 中的 this.requestComplete = this.bookFlights[0].complete; 中获取了停止标志;
    • @SumanKumar 好吧,你可以使用 pipe() 来处理你使用 post RXJS 6 链接方法的任何 observable。
    【解决方案3】:

    您的问题不是您不知道如何进行间隔调用,而是如何结束它。

    您的答案是“takeUntil”方法。 这样您就可以以声明方式结束订阅。

    private ngUnsubscribe: Subject<any> = new Subject();
    ...
    this.httpClient.post(<shortened for brevity>).pipe(interval(1000), takeUntil(this.ngUnsubscribe)).subscribe((data: any) => {
    
    // do something with your data. If you got the data from the backend, the flag that disables the subscribable you can do...
    this.ngUnsubscribe.next(); 
    })
    

    takeUntil 方法将在传递新值时停止任何订阅。

    【讨论】:

      猜你喜欢
      • 2016-07-21
      • 1970-01-01
      • 2021-06-16
      • 1970-01-01
      • 1970-01-01
      • 2012-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多