Madpop
Madpop

Reputation: 725

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

Here I have query that how can I call a interval method in the subscribe and stop it after the condition is met

below is my code

Main Subscribe method

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

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

})

Interval Method:

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

In the response it gives 3 types of response

Proceed

Stop

Terminate

So here I need to call that getInterval() in Main subscribe method and until GetInterval gives me Proceed as response or until 1 min from polling I have set the interval running if either of this conditions are met i have to stop polling.

Note: I dont need polling for Main Subscribe method if main subscribe give response on success then only I have starte this polling

Update: The below Method works but here i need 2 things

  1. How can set variables and store the response in that

  2. How can i set the boolean variable based on res like if the response comes

    this.content =true like wise

    because when i am trying to set the variables in switchMap it is not accepting

    this.authservice.getdata().pipe( switchMap(resp => timer(0, 5000).pipe( // need to store this response in global variable so that it can be used for further switchMap(t => this.authservice.getIntervalData( <1st response param> ).pipe( map(data => [data, t]))) takeWhile(([data, t]) => data !== 'TERMINATE' && t < 12), map(([data, t]) => data) )) ).subscribe(data => console.log(data))

Upvotes: 2

Views: 2735

Answers (3)

Rafi Henig
Rafi Henig

Reputation: 6432

Consider implementing it as demonstrated below:

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 
  ))

Update:

"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
  ))

Upvotes: 0

bryan60
bryan60

Reputation: 29345

you probably want to just use operators and observables....

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))

something like that is how I would implement this.

Upvotes: 5

Owen Kelvin
Owen Kelvin

Reputation: 15083

Consider using Subject to store the global variable. This way you will avoid subscribing altogether

Below Solution is tested on 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): ''),
  
  )

We define a variable

stopTime$ = timer(60000);

This emits once after 60000ms ie 1Min

Next we define

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

We will use this observable to terminate the timer when condition is met using takeUntil operator and calling the next() function on the observable

We then define

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

this observable will emit with 0 delay every 5000ms until either stopTime$ observable is called or terminateAction$ is called

We then create a subject to store our global variables. Since observables are asynchronous, to avoid values being undefined, it would make sense to use observables to store our variables and subscribe to this variables whenever we need them

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

Finally we define our interval Data 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})) stores the global variable tap(res => res === 'Terminate' ? this.terminateSubject$.next(true): '') Terminates the interval observable

Upvotes: -1

Related Questions