What is the best way to invoke an observable service a limited number of times and continue until a specific condition is satisfied with a predefined interval?

I would like to achieve the following:

  1. Make a service call only 30 times OR until a specific condition is met.

  2. The service must be called every 5 seconds.

  3. It would be great if I could see only one console.log in the subscribe function.

Let's say the condition for stopping the service calls is when accuracy drops below 50. I started with the provided code but ran into call stack issues. Can anyone provide working code for this scenario? I am asking for help here while continuing my own search for a solution. If I manage to find it on my own, I will come back and share the answer. I may not have much experience in this area, but I am determined to learn as much as I can.

public randomExample() {

    this.randomNumber().pipe(
      map((n) => {
        console.log('map', n);
        if (n.accuracy > 50) {
          throw n;
        }
        return n;
      }),
      retryWhen(e =>
        e.pipe(
          tap(n => console.log('value to high', n))
        )),
      delayWhen(n => timer(5000))
    ).subscribe((n) => {
      console.log('subscribed', n);
    })

  }

  public randomNumber(): Observable<{accuracy:number}> {
    const n = Math.floor(Math.random() * 100)
    let value = {accuracy:n}
    return of(value);
  }

Answer №1

If you want to validate both the index and value, you can utilize the takeWhile method followed by using switchMap to trigger your API:

function exampleFunction() {
  interval(500)
    .pipe(
      switchMap(() => this.randomNumber()),
      takeWhile((n, index) => index < 30 && n.accuracy >= 50, true),
      switchMap(n => {
        // Make an API call here and return observable
      }),
    )
    .subscribe(n => {
      console.log('subscribed', n)
    })
}

Answer №2

function generateRandomNumber(): { accuracy: number } {
  const num = Math.floor(Math.random() * 100);
  let value = { accuracy: num };
  return value;
}
interval(5000)
  .pipe(
    scan((acc, curr) => acc + 1, 0),
    takeWhile((count) => count <= 30),
    map(() => generateRandomNumber()),
    // tap((val) => console.log(val.accuracy)),
    takeWhile((val) => val.accuracy < 50),
    switchMap(() => of(Math.random() * 100).pipe(catchError(() => EMPTY)))
  )
  .subscribe((result) => {
    console.log("subscribed", result);
  });
  1. The interval will trigger this function every 5 seconds.

  2. scan acts as an accumulator that increments count on each interval emit.

  3. takeWhile unsubscribes automatically once the count exceeds 30.

  4. takeWhile keeps the interval active until the randomNumber generator produces a value less than 50, as we specify to unsubscribe if the value is not less than 50.

  5. If the above conditions do not trigger an unsubscribe, we call our API using switchMap. If the API returns an error, we return an EMPTY observable using catchError to ensure the polling continues.

  6. The subscribe block is executed only when the API call completes successfully.

Working link :- https://codesandbox.io/s/falling-flower-nblzz?file=/src/index.ts:219-726

If you prefer randomNumber to be an Observable :-

function generateRandomNumber(): Observable<{ accuracy: number }> {
  const num = Math.floor(Math.random() * 100);
  let value = { accuracy: num };
  return of(value);
}
interval(5000)
  .pipe(
    scan((acc, curr) => acc + 1, 0),
    takeWhile((count) => count <= 30),
    mergeMap(() => generateRandomNumber()),
    takeWhile((val) => val.accuracy < 50),
    switchMap(() => of(Math.random() * 100).pipe(catchError(() => EMPTY)))
  )
  .subscribe((result) => {
    console.log("subscribed", result);
  });

Working link :- https://codesandbox.io/s/wonderful-hill-mtxi5?file=/src/index.ts:220-701

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Designing a function declaration that filters out null values from a combined type

I've recently started the process of converting all my code to support strictNullChecks. I have a specific requirement for a function that I need to implement: function defaultValue<TUnionNull>(value: TUnionNull, default: TWithoutNull): TWithou ...

What is the process through which Typescript determines the property types of union types?

I am implementing a unique set of types to enable angular form typing: import { FormArray, FormControl, FormGroup } from '@angular/forms'; export type DeepFormArray<T, U extends boolean | undefined = undefined> = T extends Array<any> ...

Pagination problem arises when sorting through items

I am facing an issue with filtering items on different pages of my React website. The problem I encounter is that the filtering functionality only works on the initial page where the data is loaded. Code: CustomersEpolicyPage.tsx import React, {useEffect ...

What is the best way to construct a collection of promises' results by utilizing a for loop?

In the process of developing an Angular application to display articles and votes from my website, I aim to sort them based on their votes. The strategy involves making HTTP calls as follows: Initiate an HTTP call to fetch the list of categories along wi ...

Tips for saving data from an observable into a variable or property

I've been diligently working on a project utilizing both Angular and Firebase/Firestore. Here is the code snippet that I have implemented: this.cadet = this.cadetCollection.valueChanges().subscribe(x => { this.cadetName = x[0].Cadet; this.cad ...

Looking for guidance on enhancing the dynamism of my Angular dynamic form

Exploring Angular has been a great experience for me and this website has been instrumental in helping me develop applications. One of the projects I have worked on involved creating dynamic forms using JSON data, which allows for the creation of forms wit ...

Geometric structures in the style of Minecraft: Hexagonal Voxel Design

I'm attempting to create a hexagonal map by following the example at . Is there a way to generate hexagons instead of cubes? Using the first option from the manual resulted in creating a hexagonal mesh and positioning it. However, the second option ...

How do I specifically indicate that K is the exact keyof T in TypeScript?

I am enhancing my pick function and here is my current implementation: export function pick<T, K extends keyof T>(obj: T, keys: K[]): Partial<T> { const ret = Object.create(null) for(const key of keys) { ret[key] = obj[key] ...

Error: When trying to run the `ng build` command in Git Bash, TypeScript module cannot be

When attempting to execute ng build using Git Bash, I encountered this error message, even though I had previously executed npm install -g typescript. Where should I place the typescript installation so that Git can detect it? Error $ npm install -g typ ...

Error in SvelteKIt: Unable to access session due to a function being called outside of

Using Typescript in SvelteKit, I have an .ts file located in the $lib folder. Attempting to access the user/session from '$app/stores' within the .ts file results in the following code snippet: import { get } from 'svelte/store'; i ...

Embracing PWAs with subdomains – seamless installation

One of my Progressive Web Applications (PWA) called app A contains a link to another app, app B. Initially, I hosted both apps on the same subdomain (for example: ) and everything worked perfectly - installing app A also installed app B. However, when I a ...

Having issues with unexpected token in Typescript while using "as HTMLElement" type?

I recently started learning Typescript and I encountered an error while using the HTMLElement type in a forEach loop: ERROR in ./app/javascript/mount.jsx Module build failed (from ./node_modules/babel-loader/lib/index.js): SyntaxError: /Users/me/projects/m ...

The output from Typescript Box results in a union type that is overly intricate to illustrate

Encountering an error while trying to render a Box: Received error message: Expression produces a union type that is too complex to represent.ts(2590) Upon investigation here, it seems that this issue arises from having both @mui/material and @react-thr ...

utilize makeStyles to modify button text color

Initially, my button was styled like this: style={{ background: '#6c74cc', borderRadius: 3, border: 0, color: 'white', height: 48, padding: '0 30px', }}> It worke ...

Module 'csstype' not found

I am diving into the world of React with TypeScript. After setting up react and react-dom, I also installed @types/react and @types/react-dom which all went smoothly. However, a pesky error message keeps popping up: ERROR in [at-loader] ./node_modules/@t ...

Navigating with Angular: Incorporating Deprecated Router with NgModule

I have recently made some changes in my Angular project, switching from rc4 to rc5 and incorporating a module in main.ts: import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { PortmanModule } from './portman. ...

Encountering an issue: The module ' ode_modules@sentryprofiling-nodelibsentry_cpu_profiler-win32-x64-120.node' could not be located

[ERROR] 22:19:26 Error: Unable to locate module 'D:\Toystack\toystack-core-backend\node_modules@sentry\profiling-node\lib\sentry_cpu_profiler-win32-x64-120.node' Require stack: D:\Toystack\to ...

Incorporate Font Awesome icons throughout your Angular8 application for added visual appeal

I'm currently working on a large Angular application that utilizes lazy loading modules. Throughout various components in different modules, I make use of icons from Font Awesome individually. Here is an example: In component.ts: import { faChevronD ...

Error Handling in Angular2 MVC 4 Project Route Issues

Here is the structure of my Mvc 4 Project with angular 2 implemented: Solution 'Angular2Starter' |-- angular2Starter | `-- Controllers | `-- HomeController.cs |-- src | |-- app | | |-- home | | | |-- home.component.ts | ...

Unable to access the ID of collections in Firestore

Having trouble accessing data in nested collections within a collection? I've been attempting to retrieve the data from a collection, then from a document inside that collection, and finally another collection within that document. Unfortunately, I ...