Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

332
Vistas
How to repeat a promise conditionally using rxjs

I would like to repeat an API call which returns a Promise, conditionally using rxjs.

The API method receives an id which will be changed on every call by adding a counter prefix to it. The calls will be repeated until the data met some condition or the counter reach to a specific number X. How it can be done using rxjs?

API method:

fetchData(id):Promise<data>

try 1: fetchData(id)

try 2: fetchData(id_1)

try 3: fetchData(id_2)

about 4 years ago · Juan Pablo Isaza
3 Respuestas
Responde la pregunta

0

IMO, it's better to handle the polling either through Promises or RxJS without mixing them. I'd illustrate using RxJS.

Try the following

  1. Convert the promise to an observable using the RxJS from function.
  2. Use RxJS functions like timer or interval to regularly emit a value on a fixed interval.
  3. Use a higher order mapping operator like switchMap to map from the outer emission to your API call. Refer here for a brief description about different types of higher order mapping operators.
  4. Use two takeWhile operators, one for each of your condition respectively, to complete the subscription.
  5. Use filter operator to only forward the emissions that pass the condition.
import { from } from 'rxjs';

fetchData(id: any): Observable<any> {  // <-- return an observable
  return from(apiCall);                // <-- use `from` to convert Promise to Observable
}
import { timer } from 'rxjs';
import { filter, switchMap, takeWhile } from 'rxjs/operators';

timer(0, 5000).pipe(                        // <-- poll every 5 seconds
  takeWhile((index: number) => index < 20)  // <-- stop polling after 20 attempts
  switchMap((index: number) => 
    this.someService.apiCall(index+1)       // <-- first emission from `timer` is 0
  ),
  takeWhile(                                // <-- stop polling when a condition from the response is unmet
    (response: any) => response.someValue !== someOtherValue,
    true                                    // <-- emit the response that failed the test
  ),
  filter((response: any) => 
    response.someValue === someOtherValue   // <-- forward only emissions that pass the condition
  )
).subscribe({
  next: (response: any) => {
    // handle response
  },
  error: (error: any) => {
    // handle error
  }
});

Edit: The condition in the 2nd takeWhile was doing the opposite of the requirement. I've adjusted the condition and included the inclusive=true argument. Thanks @Siddhant in the comments.

about 4 years ago · Juan Pablo Isaza Denunciar

0

You can use concatMap to ensure only one call is tried at a time. range gives the maximum number of calls because takeWhile will unsubscribe early (before the range is done) if a condition is/isn't met.

That might look like this:

// the data met some condition
function metCondition(data){
  if(data/*something*/){
    return true;
  } else {
    return false
  }
}

// the counter reach to a specific number X
const x = 30;

range(0, x).pipe(
  concatMap(v => fetchData(`id_${v === 0 ? '' : v}`)),
  takeWhile(v => !metCondition(v))
).subscribe(datum => {
  /* Do something with your data? */
});
about 4 years ago · Juan Pablo Isaza Denunciar

0

You could try retryWhen:

let counter=0;

const example = of(1).pipe(
  switchMap(x => of(counter)), // Replace of() with from(fetchData('id_'+counter))
  map(val => {
    if (val < 5) {
      counter++;
      // error will be picked up by retryWhen
      throw val;
    }
    return val;
  }),
  retryWhen(errors =>
    errors.pipe(
      // log error message
      tap(val => console.log(`Response was missing something`)),
    )
  )
);

It's not ideal as it needs a counter in the outer scope, but until there is a better solution (especially without time based retries) this should work.

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda