简体   繁体   English

如何在 Angular 8 中定期调用异步方法?

[英]How to call async method after regular interval of time in Angular 8?

I'm calling an API which runs in for loop, but we want to wait for 1-2 seconds before hitting the API everytime inside the loop, so we made the method as async and added await before hitting the apiMethod.我正在调用在 for 循环中运行的 API,但我们希望等待 1-2 秒,然后每次在循环内点击 API,因此我们将该方法设置为异步并在点击 apiMethod 之前添加等待。

But I also want to call the async method after every 5 minutes, so I added the interval method just before closing the async method.但是我也想在每 5 分钟后调用一次异步方法,所以我在关闭异步方法之前添加了间隔方法。 But it behaves weirdly, sometimes it waits for 5 min before invoking the method again, sometimes it calls it multiple times, and sometimes before 5 min is over.但它的行为很奇怪,有时会等待 5 分钟再调用该方法,有时会多次调用它,有时会在 5 分钟结束之前。 Any help?有什么帮助吗?

async fetchData(){

for(let index=0;index<rollNo[].length; index++){ 

 await new Promise(r => setTimeout(r, 2000)); //delay of 2 sec before passing the next rollNo

//calls the service
  let  subscription = callAPIMethod(rollNo[index]).subscribe((data) => {
  this.Response = data;
  
  subscription.unsubscribe();

}, (error) => {
  this.showToasterMessage('', 'We encountered an error', 'error');
  return;
}); 
}


 //Wait for 5 min before starting all over again
 interval(300000).subscribe(x => {
      this.fetchData();
    });

}

I did try .pipe(delay(2000)) before making the method async but all it does is wait for 2 seconds and then run the entire for-loop at once which I don't want.在使方法异步之前,我确实尝试.pipe(delay(2000)) ,但它所做的只是等待 2 秒,然后一次运行整个 for 循环,这是我不想要的。 Interval or setTimeOut works only when the method is not async, but if I don't make the method as async then I can't wait for 2 seconds before hitting the API everytime. Interval 或 setTimeOut 仅在方法不是异步的情况下才有效,但如果我不将该方法设为异步,那么我每次都无法等待 2 秒再点击 API。

Sure you can get it using another approach and the timer rxjs/operator.当然,您可以使用另一种方法和计时器 rxjs/operator 来获得它。 An observable like一个可观察的像

obs=timer(0,1000).pipe(
      take(this.rollNo[].length),
      switchMap(_=>{
      return callAPIMethod()
    }))

If you enclosed in another timer and use tap如果您包含在另一个计时器中并使用水龙头

timer(0,30000).pipe(switchMap(_=>{
  return this.obs.pipe(tap((res)=>{
      this.Response=res;
  }))
})).subscribe()

you get it你懂了

Updated I made a "fool example" in this stackblitz .更新了我在这个 stackblitz中做了一个“傻瓜的例子”。 You can see how the observable "callAPIMethod" is called so many times as elements has the array "values" each seconds, after 10 seconds start again (really as the "values" has 4 elements, after 7 seconds aprox)您可以看到可观察的“callAPIMethod”如何被多次调用,因为元素每秒都有数组“值”,10 秒后重新开始(实际上,“值”有 4 个元素,大约 7 秒后)

Update 2 you has a code like更新 2你有一个类似的代码

//this NOT WORK, callAPIMethod return null
//in general, when we work with observables only makes actions in subscribe or in tap 
//in the main "subscription" -in the example I use tap because I want to 
//execute actions in a "inner observable"
callAPIMethod(code) {
    let subscription = this.appService
      .slotByPin(code, this.date)
      .subscribe(data => {
        this.response = data;
        this.someOperationInsideThisMethod();
        subscription.unsubscribe();
      });
  }

But you should transform, your callAPIMethod should return an Observable, so transform the code by但是你应该转换,你的 callAPIMethod 应该返回一个 Observable,所以转换代码

this.obs = timer(0, 1000).pipe(
  take(this.parameters.length),
  switchMap(index => {
    //see that index is the result of "timer", that's 0,1,2,3...
    //so we can send to the callAPIMethod parameters[index]
    return this.callAPIMethod(parameters[index]);  
  })
);
timer(0, 10000)
      .pipe(
        switchMap(_ => {
          return this.obs.pipe(
            tap(
              data => {
        //see that you put here the code you had in your "callAPIMethod"
        this.response = data;
        this.someOperationInsideThisMethod();
            })
          );
        })
      )
      .subscribe();
  
  //see how the "callAPIMethod" return an observable
  callAPIMethod(code) {
    return this.appService
      .slotByPin(code, this.date)
      
  }

Solved with this解决了这个

selectedCodes: string[] = [];

 ngOnInit() {
this.delayedLoop(this.selectedCodes.length, 0);


setInterval(() => {
  this.initializeSearch();
  this.delayedLoop(this.selectedCodes.length, 0);
}, ((5000+this.selectedCodes.length)*1000));


  delayedLoop(i:any,pIndex:any) {
    let arrLength =  i;
    let tempIndex = pIndex;
    if(this.selectedCodes && pIndex <  this.selectedCodes.length){
      let myThis = this;
      setTimeout(function() {
        myThis.fetchSlots(tempIndex,this.dateArrray);  
       
        if (--arrLength) {
          tempIndex++;
          myThis.delayedLoop(arrLength,tempIndex);
        }  
      }, 1000)
    }
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM