Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

300
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda