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

194
Visualizações
Iterar a través de la matriz de objetos Observable y agregar datos adicionales de otro Observable a cada objeto

Tengo un servicio Angular que devuelve una matriz de objetos "cleaningDuty". Dentro de un objeto de servicio, hay un objeto anidado llamado "currentCleaner" con una identificación.

 [ { // other cleaningDuty data currentCleaner: { id: string; active: boolean; }; }, { // other cleaningDuty data currentCleaner: { id: string; active: boolean; }; }, { // other cleaningDuty data currentCleaner: { id: string; active: boolean; }; } ]

con la ayuda de currentCleaner.id , quiero obtener los datos de usuario de currentCleaner de un UserService dinámicamente en el mismo método pipe() y agregar los datos de usuario devueltos al objeto cleaningDuty. Entonces el objeto debería verse así:

 { // other cleaningDuty data currentCleaner: { id: string; active: boolean; }, cleanerData: { name: string; photoUrl: string; // other user data } },

Desafortunadamente, no puedo hacer que esto funcione incluso después de invertir días en ello. Probé casi todas las combinaciones de forkJoin() , mergeMap() y así sucesivamente. Sé que un método de subscribe() dentro del componente de destino haría el trabajo, pero quiero escribir el mejor código posible en cuanto a calidad. Este es mi estado actual del método de servicio (agrega el usuario observable en lugar del valor al objeto cleaningDuty):

 getAllForRoommates(flatId: string, userId: string) { return this.firestore .collection('flats') .doc(flatId) .collection('cleaningDuties') .valueChanges() .pipe( mergeMap((duties) => { let currentCleaners = duties.map((duty) => this.userService.getPublicUserById(duty.currentCleaner.id), ); return forkJoin([currentCleaners]).pipe( map((users) => { console.log(users); duties.forEach((duty, i) => { console.log(duty); duty.cleanerInfos = users[i]; }); return duties; }), ); }), ); }

El método getPublicUserById() :

 getPublicUserById(id: string) { return this.firestore.collection('publicUsers').doc(id).valueChanges(); }

¡Cualquier ayuda sería muy apreciada!

about 4 years ago · Juan Pablo Isaza
3 Respostas
Responde à pergunta

0

La función forkJoin :

Espere a que los Observables se completen y luego combine los últimos valores que emitieron; completar inmediatamente si se pasa una matriz vacía.

Entonces, debe asegurarse de que todos los Observables internos se hayan completado, luego forkJoin emitirá los valores combinados, y puede lograrlo usando el operador take (1) , como el siguiente:

 getAllForRoommates(flatId: string, userId: string) { return this.firestore .collection('flats') .doc(flatId) .collection('cleaningDuties') .valueChanges() .pipe( mergeMap((duties) => // The `forkJoin` will emit its value only after all inner observables have been completed. forkJoin( duties.map((duty) => // For each duty, fetch the cleanerData, and append the result to the duty itself: this.userService.getPublicUserById(duty.currentCleaner.id).pipe( take(1), // to complete the sub observable after getting the value from it. map((cleanerData) => ({ ...duty, cleanerData })) ) ) ) ) ); }
about 4 years ago · Juan Pablo Isaza Relatório

0

En primer lugar, le sugiero que mejore la escritura en su aplicación, eso lo ayudará a ver el problema con más claridad. Para mi respuesta, supondré que tiene 3 interfaces definidas CurrentCleaner, CleanerData y RoomData, que son solo:

 interface RoomData { currentCleaner: CurrentCleaner cleanerData: CleanerData }

Luego, puede escribir una función de ayuda para recuperar los datos de la habitación de un limpiador actual:

 getRoomData$(currentCleaner: CurrentCleaner): Observable<RoomData> { return this.userService.getPublicUserById(currentCleaner.id).pipe( map(cleanerData => ({ currentCleaner, cleanerData })) ) }

Como puede ver, estas funciones toman un limpiador actual, obtienen los datos del limpiador y los mapean en un objeto RoomData.

Tener este próximo paso es definir su función principal

 getAllForRoommates(flatId: string, userId: string): Observable<RoomData[]> { return this.firestore .collection('flats') .doc(flatId) .collection('cleaningDuties') .valueChanges() .pipe( mergeMap((duties) => { // here we map all duties to observables of roomData let roomsData: Observable<RoomData>[] = duties.map(duty => this.getRoomData$(duty.currentCleaner)); // and use the forkJoin to convert Observable<RoomData>[] to Observable<RoomData[]> return forkJoin(roomsData) }), ); }

Creo que de esta manera es fácil entender lo que está haciendo el código.

about 4 years ago · Juan Pablo Isaza Relatório

0

  1. Compruebe si necesita switchMap o mergeMap . En mi opinión, cancelaría el observable existente cuando valueChanges() . Vea aquí la diferencia entre ellos.
  2. Use Array#map con la función forkJoin de forkJoin para activar las solicitudes en paralelo.
  3. Utilice el operador de map RxJS con sintaxis de desestructuración para agregar propiedades adicionales a los objetos existentes.
  4. Se deben utilizar tipos idealmente definidos en lugar de any tipo.

Prueba lo siguiente

 getAllForRoommates(flatId: string, userId: string) { return this.firestore .collection('flats') .doc(flatId) .collection('cleaningDuties') .valueChanges() .pipe( switchMap((duties: any) => forkJoin( duties.map((duty: any) => // <-- `Array#map` method this.userService.getPublicUserById(duty.currentCleaner.id).pipe( map((data: any) => ({ // <-- RxJS `map` operator ...duty, // <-- the `currentCleaner` property cleanerData: data // <-- new `cleanerData` property })) ) ) ) ) ); }
about 4 years ago · Juan Pablo Isaza 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