Estoy buscando ayuda o una pista para un problema con rxjs que no puedo resolver.
Básicamente, quiero activar un observable y completarlo antes del activador original.
Caso: Estoy trabajando en un proyecto en el que tengo dos perfiles, digamos profileA , profileB . A veces, el profileA A tiene algunas propiedades que necesito pasar al profileB para obtener el profileB Y al final, combino ambos perfiles y devuelvo el observable original.
Por lo general, localStorage profileA puedo obtener el profileB
getProfileB() { const url = `${..}/xyz/${this.profileB.username}/userData` return this.http.get(anUrl); // and returns the observale to the next destination } Pero a veces puede ser que el profileA A no esté disponible en el localstorage , por lo que en ese caso, primero tengo que buscar el profileA A y luego continuar con la recuperación del perfil profileB
Me gustaría usar el siguiente enfoque. Como no me importa
getProfileA() { return this.http.get(anUrlForProfileA); } getProfileB() { const url = `${..}/xyz/${this.profileB.username}/userData` return this.http.get(anUrl).pipe( aPipeOperator() => { // the null could be the mean that continue with the current Observable, whereas concatenateFirst means, first completes the getProfileA observable and then continue with the original one. return this.profileA?.username?.length > 0? concatenateFirst(this.getProfileA()) : null; } ); }Estoy luchando un poco con los rxjs, y también es difícil para mí explicarlo, así que por favor ayúdenme. Este problema podría resolverme otros problemas también.
Gracias
[Editar]: como desea usar su profileA A en su solicitud de perfil profileB , debe usar SwitchMap, como dijo Jason Goemaat . Aquí hay otro ejemplo un poco diferente para una mejor comprensión del principiante que el suyo:
export class AppComponent implements OnInit { ngOnInit() { this.getProfileB(); } getProfileA(): Observable<{ name: string, profile: string }> { return of({ profile: "A", name: 'Quentin' }); } getProfileB() { this.getProfileA().pipe( switchMap(profileA => { // ProfileA is completed, you can acces its value console.log(profileA); // return another observable (For you, your api call for ProfileB) return of({profile: "B", name: "John", profileA}); }), ).subscribe(profileB => { // Get profileB value here console.log(profileB); }) } } De su ejemplo, parece que podría usar forkjoin() . Espera a que se completen todos los observables antes de continuar, por lo que podrías hacer algo así:
forkJoin(getProfileA(), this.http.get(anUrlForProfileB)).pipe( mergeMap(obs => { //... use obs[0] and obs[1] to access your observable values} );Creo que switchMap es lo que estás buscando. Le pasa una función que tomará el resultado de su observable y devolverá un observable para reemplazarlo.
const getProfileA = () => of({ name: 'A' }) const getProfileB = (profileA: any) => { const requestProfileB = of({ name: 'B', message: `This is profile B, using data from profile with name '${profileA.name}'`}) return requestProfileB.pipe(map(profileB => ({ profileA, profileB }))) } getProfileA().pipe(switchMap(getProfileB)).subscribe(x => console.log(x)) Aquí getProfileA imita una llamada http para devolver el perfil 'A'. Ese resultado se canaliza a switchMap que pasa getProfileB . Esa función toma profileA y crea requestProfileB usando datos de profileA. Eso se canaliza a map() que combina el resultado de la solicitud de profileB con el valor pasado para profileA en un objeto que se emitirá cuando se suscriba el resultado. Resultado:
{ "profileA": { "name": "A" }, "profileB": { "name": "B", "message": "This is profile B, using data from profile with name 'A'" } }