【问题标题】:Call a function every 10 seconds Angular2每 10 秒调用一次函数 Angular2
【发布时间】:2018-02-16 04:56:42
【问题描述】:

我正在尝试创建一个Timer,它每 10 秒调用一次API call,我正在使用setTimeOut,但问题是它变成了一个无限循环,即使我推到另一个页面它继续加入 if 条件。

例子:

我在一个方法上调用它来启动 10 秒 API 调用

setTimeout(() => {
    this.onTimeOut();
}, 1000);

这就是onTimeOut() 方法...

onTimeOut() {
    this.ApiCall().then(
    success => {
    if(success ['ok'] == 0){
        this.navCtrl.push(myPage);
    }
    },
    error => { console.log(error); });
}
setTimeout(() => {
    this.onTimeOut();
}, 1000);
}

我听说过Debouncerxjs/rs,但我对它们并不熟悉,你能给我一些提示吗?或者,如果这种方式更有效,请继续向我解释为什么它会变成循环。

目标是当它加入if并push页面时,停止定时器。

【问题讨论】:

  • 您说“10 秒”但将}, 1000); 传递给setTimeout

标签: angular typescript ionic-framework ionic2


【解决方案1】:

RxJS 6+ 你只需使用区间。

import { interval } from 'rxjs';

//in 10 seconds do something
interval(10000).subscribe(x => {
    this.myFunctionThatDoesStuff();
});

您可以将Subscription 与间隔一起使用。

import { interval, Subscription} from 'rxjs';
export class intervalDemo{
    mySubscription: Subscription

    constructor(){
    this.mySubscription= interval(5000).subscribe((x =>{
                this.doStuff();
            }));
    }
    doStuff(){
        //doing stuff with unsubscribe at end to only run once
        this.failedRequestSub.unsubscribe();
    }
}

【讨论】:

  • 当我使用它时。首先它等待 5 秒然后只有它做的东西。然后等5秒怎么办?
  • 简单的方法是在开始间隔之前调用该函数。
  • 记得在完成后删除间隔。如果您只取消订阅,则间隔仍将继续运行。我更喜欢使用takeUntil,例如:this. mySubscription = interval(5000).pipe(takeUntil(this.destroy$)).subscribe(() => { doStuff(); }) 并删除它:ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); }
【解决方案2】:

更好地使用 observables

this.sub = Observable.interval(10000)
    .subscribe((val) => { console.log('called'); });

停止使用

this.sub.unsubscribe();

确保使用

导入interval
import 'rxjs/add/observable/interval';

【讨论】:

  • 什么是“this.sub”?
  • 类级字段sub:Subscription;
  • 我必须导入一些东西吗?
  • 一切,一如既往。 Observable, Subscription 如果你输入它。我不知道进口情况,但每个问题都有一个答案;-)
  • import { interval } from 'rxjs'; 可以与最新版本的 Angular 一起使用,请参阅 stackoverflow.com/questions/37074485/…
【解决方案3】:

setTiimeout 没有任何问题,只是代码中的一个错误。这确实是一个无限循环(没有基本条件的递归函数),因为那里没有任何基本条件。

因此,setTimeout 将在每 1 秒后继续调用 onTimeOut(),因为它不知道在哪里停止。当你切换到其他页面时,只需使用一个基本条件来完成递归。

 private flag: boolean;

 ngOnInit() {
        this.flag = true;
 }

 ngOnDestroy() {
        this.flag = false;
 }
 onTimeOut() {
        this.ApiCall().then(
        success => {
        if(success ['ok'] == 0){
            this.navCtrl.push(myPage);
        }
        },
        error => { console.log(error); });
    }
     setTimeout(() => {
     if(this.flag){
        this.onTimeOut();
     }
    }, 1000);
    }

ngOnDestroy 方法会将标志设置为 false 并且递归函数的最后一次调用不会进入 if 块内,因为此后没有任何内容要执行,它将返回(之前的状态)并将它从堆栈中清除,这个过程将重复直到堆栈被清除(同样的事情会发生在它的先前版本上,它现在位于堆栈的顶部,因此将递归地一个一个地清除堆栈)。

【讨论】:

    【解决方案4】:

    在 Angular 应用中比 setTimeout 更好的解决方案是使用 Observable。 Observable 有一个名为 timer 的方法,您可以通过这种方式使用(也有一个 TimerObservable,但我从未使用过它,所以我不知道这是不是同一件事):

    timer = Observable.timer(initialDelay, period);
    
    timer.subscribe(tick => {
       // Your API call, which will be performed every period
    });
    

    我鼓励你也使用 RxJS 和 Observable 来处理你的请求,而不是 Promise,它更像是 Angular 对我做事的方式,而且 RxJS 是一个非常强大的库。

    RxJS Observable doc

    【讨论】:

    • 我喜欢这个,但是如果 api 有时碰巧很慢怎么办?作为对此的扩展,是否有可能在每个滴答声中调用 api,除非之前的调用尚未完成?如果上一个调用尚未完成,下一个调用应安排在上一个调用完成后立即进行。
    • 由于 HTTP 调用是异步的,因此执行此类操作可能很困难。您可以尝试像这样使用回调和 Observable:jsfiddle.net/mrv4rLbd
    • 您可以使用debounce 运算符:rxjs-dev.firebaseapp.com/api/operators/debounce。我没有尝试过,但存储最后一个 API 调用并对其进行去抖动可能会起作用。
    【解决方案5】:

    以角度方式使用observable.timer 来达到您的目的。

     export class CurrentRunsComponent implements OnInit, OnDestroy {
      private timer;
    
    
      ngOnInit() {
        this.timer = Observable.timer(10000);
        this.timer.subscribe((t) => this.onTimeOut());
      }
       onTimeOut() {
        this.ApiCall().then(
        success => {
        if(success ['ok'] == 0){
            this.navCtrl.push(myPage);
        }
        },
        error => { console.log(error); });
    }
    
       ngOnDestroy(){
        console.log("Destroy timer");
    
      }
    }
    

    【讨论】:

    • +1 用于提及不执行初始延迟的计时器。导入导入'rxjs/add/observable/timer';而是
    猜你喜欢
    • 2023-03-16
    • 2011-08-06
    • 2017-11-22
    • 1970-01-01
    • 2011-11-06
    • 2011-03-09
    • 1970-01-01
    相关资源
    最近更新 更多