Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

295
Views
Rxjs - Cadena de llamadas http con Observables

Quiero hacer 3 llamadas http que devuelvan un valor booleano. Lo que quiero es hacer la próxima llamada solo si el resultado de la llamada anterior es true

ES DECIR:
call1() -> si es false , detener, si es true :
call2() -> si es false , detener, si es true :
call3()

ahora lea los resultados de una manera que indique qué llamada devolvió false si es así.

mi primer intento con switchMap:

 this.call1() .pipe( switchMap((r1) => (r1 ? this.call2() : of(false))), switchMap((r2) => (r2 ? this.call3() : of(false))) ) .subscribe((r) => { console.log('inside subscribe:', r); });

el problema aquí es que ahora dentro de la suscripción me sale:
'inside subscribe:' false
y no puedo saber si el resultado falso es de call1,2 o 3.

entonces mi solución es guardar los resultados en una matriz externa, así:

 // seriel execution with switchMap, we can use each result to the next call // + save all results const results = [false, false, false]; this.call1() .pipe( // save stage1 result tap(r1 => results[0] = r1), // if true, make call2, else return false switchMap((r1) => (r1 ? this.call2() : of(false))), // save stage2 result tap(r2 => results[1] = r2), // if true, make call3, else return false switchMap((r2) => (r2 ? this.call3() : of(false))), // save stage3 result tap(r3 => results[2] = r3), ) .subscribe((r) => { console.log('inside subscribe:', r); // r is the latest value results[2] console.log('all results:', results) // array of all stages [true,false,false] }); }

y parece funcionar, pero ¿tal vez hay otra forma sin trabajo externo? solo con operadores rxjs?

Enlace de Stack Blitz:
https://stackblitz.com/edit/angular-rxjs-playground-zjnh7u?devtoolsheight=33&file=app/app.component.ts

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

Tal vez algo como esto puede funcionar

 this.call1() .pipe( switchMap((r1) => (r1 ? this.call2() : of(false).pipe(tap(() => console.log('r1 returns false')), switchMap((r2) => (r2 ? this.call3() : of(false).pipe(tap(() => console.log('r2 returns false'))), tap(respOfR3 => if(!respOfR3) {console.log('r3 returns false')}) ) .subscribe((r) => { console.log('inside subscribe:', r); });

Al mismo tiempo, considere que la secuencia de booleanos notificados por su primer Observable contiene implícitamente la información que está buscando. De hecho, la posición del primer falso que encuentra refleja la primera llamada que ha devuelto false .

over 4 years ago · Santiago Trujillo Report

0

Adjuntaría la fuente al resultado: lo más simple es una tupla [number, boolean] , donde el primer elemento en la tupla/matriz es la fuente. Una variación de la solución switchMap es:

 this.call1() .pipe( map((result) => [1, result]), switchMap((r1) => (r1[1] ? this.call2().pipe(map((result) => [2, result])) : of(r1))), switchMap((r2) => (r2[1] ? this.call3().pipe(map((result) => [3, result])) : of(r2))) ) .subscribe((r) => { console.log('inside subscribe:', r); });

Esto tiene un patrón y es un poco detallado, podemos hacerlo mejor:

 function attachSource(source: number, target: Observable<boolean>): Observable<[number, boolean]> { return target.pipe(map((result) => [source, result])); } attachSource(1, this.call1()) .pipe( switchMap((r1) => (r1[1] ? attachSource(2, this.call2()) : of(r1))), switchMap((r2) => (r2[1] ? attachSource(3, this.call3()) : of(r2))) ) .subscribe((r) => { console.log('inside subscribe (try2):', r); });

Y si generalizamos un poco más, dado lo siguiente:

 function attachSource<T>(source: number, target: () => Observable<T>): Observable<[number, T]> { return target().pipe(map((result) => [source, result])); } function series<T>(failed: (arg: T) => boolean, ...factories: (() => Observable<T>)[]): Observable<[number, T]> { return factories.reduce((agr, cur, index) => { if (index === 0) { return attachSource(index+1, cur); } else { return agr.pipe(switchMap((prevResult) => failed(prevResult[1]) ? of(prevResult) : attachSource(index+1, cur))); } }, empty<[number, T]>()); }

Puede ser tan simple como:

 series((x: boolean) => x, this.call1.bind(this), this.call2.bind(this), this.call3.bind(this)) .subscribe((r) => { console.log('inside subscribe (try3):', r); });
over 4 years ago · Santiago Trujillo Report

0

Aquí hay una solución muy limpia que usa el operador de expansión para llamadas recursivas

 const results = [false, false, false]; let count = 0; this.call().pipe( tap(response => { results[count] = response count++ } ), expand((response) => response && count < 3 ? this.call() : EMPTY ) ).subscribe((r) => { console.log('inside subscribe:', r); // r is the latest value results[2] console.log('all results:', results) // array of all stages [true,false,false] });

Y realmente no necesita la función de llamada múltiple (llamada1, llamada2, llamada3), solo una será suficiente

 call(): Observable<boolean> { let bool: boolean = this.randBool(); return of(bool); } private randBool(): boolean { return Math.random() < 0.5 }

https://stackblitz.com/edit/angular-rxjs-playground-zvfpay?file=app/app.component.ts

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!