如果在 Angular 中满足条件,如何 运行 并停止订阅中的间隔方法

How to run and stop the interval method in the subscribe if condition is met in Angular

这里我有疑问,如何在订阅中调用间隔方法并在满足条件后停止它

下面是我的代码

主要订阅方法

this.authservice.getdata().subscribe(response => {
   console.log(res)

   // Polling method
    
    SetInterval(()=>{
     this.getInterval();
   },5000)

})

区间法:

getInterval(){
  this.authservice.getIntervalData().subscribe(resp => {
    console.log(resp)
   this.responseStatus = resp
  })
}

在响应中给出了 3 种类型的响应

继续

停止

终止

所以在这里我需要在 Main subscribe 方法中调用 getInterval() 直到 GetInterval 给我 Proceed 作为响应或者直到轮询 1 分钟后我设置了间隔 运行 如果满足任何一个条件我必须停止投票。

注意:我不需要轮询 Main Subscribe 方法,如果 main subscribe 给出成功的响应,那么只有我开始这个轮询

更新: 下面的方法有效,但这里我需要两件事

  1. 如何设置变量并将响应存储在其中

  2. 如果有响应,我如何设置基于 res 的布尔变量

    this.content =真聪明

    因为当我尝试在 switchMap 中设置变量时它不接受

    this.authservice.getdata().管道( switchMap(resp => timer(0, 5000).pipe( // 需要将此响应存储在全局变量中,以便进一步使用 switchMap(t => this.authservice.getIntervalData( <第一个响应参数> ).pipe( map(data => [data, t]))) takeWhile(([data, t]) => data !== 'TERMINATE' && t < 12), 地图(([数据,t])=>数据) )) ).subscribe(数据=> console.log(数据))

您可能只想使用运算符和可观察值....

this.authservice.getdata().pipe( // get initial data
  tap(resp => this.myVariable = resp),
  switchMap(resp => timer(0, 5000).pipe( // switch to timer that emits every 5 seconds
    switchMap(t => this.authservice.getIntervalData().pipe( // swtich again to interval data
      map(data => [data, t]))) // map to response and timer value
    takeWhile(([data, t]) => data !== 'TERMINATE' && t < 12), // whatever stop condition, this says stop when the data is terminate or the timer has emitted 12 times (1 minute if emitting every 5 seconds)
    map(([data, t]) => data) // just send the data through
  ))
).subscribe(data => console.log(data))

类似的是我将如何实现它。

考虑如下所示实施它:

this.authservice.getdata().pipe(
  tap(x => this.globalVariable = x),
  switchMap(data => interval(5000).pipe(
    switchMap(x => this.authservice.getIntervalData(x)), //<== pass data from first subscription to second
    takeUntil(timer(60 * 1000)),
    takeWhile(x => x !== 'TERMINATE'),
    map(data2 => [data, data2]) // <= return values from both subscriptions 
  ))

更新:

"stop this interval outside of method i mean like a button click"

clicked$ = new Subject<void>();

onclick(){
  this.clicked.next(); // on click emit value
}


this.authservice.getdata().pipe(
  tap(x => this.globalVariable = x),
  switchMap(data => interval(5000).pipe(
    switchMap(x => this.authservice.getIntervalData(x)), //<== pass data from first subscription to second
    takeUntil(timer(60 * 1000)),
    takeWhile(x => x !== 'TERMINATE'),
    map(intervalDataRes => this.condition = intervalDataRes),
    takeUntil(merge(this.clicked$, timer(2 * 60 * 1000))) // interval will stop after 2 or as soon as clicked$ emits
  ))

考虑使用Subject来存储全局变量。这样您就可以完全避免订阅

以下解决方案在 stackblitz 上进行了测试,see this link

  // Emit Once after 60 Seconds
  stopTime$ = timer(60000);

  // TerminateResponse
  terminateSubject$ = new Subject();
  terminateAction$ = this.terminateSubject$.asObservable();

  // Emits Every 5 seconds until stopTime is called
  interval$ = timer(0, 5000).pipe(
    takeUntil(this.stopTime$),
    takeUntil(this.terminateAction$),
  );

  // Global Variable
  responseSubject$ = new Subject()
  responseAction$ = this.responseSubject$.asObservable();

  // Create Interval Observable. This will call getIntervalData until no more interval
  intervalData$ = this.interval$.pipe(
    switchMap(() => this.authservice.getIntervalData()),
    tap(res => this.responseSubject$.next({res, content: true})),
    tap(res => res === 'Terminate' ? this.terminateSubject$.next(true): ''),
  
  )

我们定义一个变量

stopTime$ = timer(60000);

这会在 60000 毫秒后发出一次,即 1 分钟

接下来我们定义

 terminateSubject$ = new Subject();
 terminateAction$ = this.terminateSubject$.asObservable();

当条件满足时,我们将使用此可观察对象终止计时器,使用 takeUntil 运算符并在可观察对象上调用 next() 函数

我们接着定义

interval$ = timer(0, 5000).pipe(
    takeUntil(this.stopTime$),
    takeUntil(this.terminateAction$),
  );

此 observable 将每 5000 毫秒以 0 延迟发射,直到 stopTime$ observable 被调用或 terminateAction$ 被调用

然后我们创建一个主题来存储我们的全局变量。由于 observables 是异步的,为了避免值未定义,使用 observables 来存储我们的变量并在我们需要它们时订阅这个变量是有意义的

  responseSubject$ = new Subject()
  responseAction$ = this.responseSubject$.asObservable();

最后我们定义了我们的区间数据 Observable

  intervalData$ = this.interval$.pipe(
    switchMap(() => this.authservice.getIntervalData()),
    tap(res => this.responseSubject$.next({res, content: true})),
    tap(res => res === 'Terminate' ? this.terminateSubject$.next(true): ''),

  )

tap(res => this.responseSubject$.next({res, content: true}))存放全局变量 tap(res => res === 'Terminate' ? this.terminateSubject$.next(true): '') 终止 interval observable