Как правильно добавить поля во все объекты массива документов FireStore с помощью RxJS?

Я схожу с ума от следующей проблемы RxJS.

В классе обслуживания Angular у меня изначально был этот метод, извлекающий данные из базы данных Firebase FireStore:

async getAllEmployees() { 
    return <Observable<User[]>> this.firestore.collection('users',ref => ref.where('profileType', '!=', 'admin')).valueChanges();          
  } 

возвращающий Observable, содержащий массив объектов User. Это прекрасно работает.

Этот метод службы вызывается методом кода компонента TypeScript, вот этот:

async loadEmployeesList() {
    this.employeesList$ = await this.employeeService.getAllEmployees();
    console.info("employeesList$: ", this.employeesList$);
}

Теперь у меня есть следующая проблема: я должен добавить вычисляемое поле к каждому объекту, полученному FireStore. Это поле имеет полное имя и является конкатенацией следующих двух полей: имя и фамилия.

Поэтому я попытался сделать это следующим образом, используя RxJS:

  async getAllEmployees() { 
    //return <Observable<Employee[]>> this.firestore.collection('users',ref => ref.where('profileType', '!=', 'admin')).valueChanges(); 
    
    return <Observable<Employee[]>> <unknown>this.firestore.collection('users', ref => ref.where('isEmployee', '==', true)).snapshotChanges()
      .subscribe(snaps => {
        snaps.map(snap => {
          console.info("CURRENT SNAP: ", snap);

          let currentEmployee: Employee = {
            id: snap.payload.doc.id,
            firstName: snap.payload.doc.get("firstName"),
            surname: snap.payload.doc.get("surname"),
            completeName: snap.payload.doc.get("firstName") + " " + snap.payload.doc.get("surname"),
            placeOfBirth: snap.payload.doc.get("placeOfBirth"),
            socialSecurityCode: snap.payload.doc.get("socialSecurityCode"),
            birthDate: snap.payload.doc.get("birthDate"),
            companyEmail: snap.payload.doc.get("companyEmail"),
            personalEmail: snap.payload.doc.get("personalEmail"),
            companyPhone: snap.payload.doc.get("companyPhone"),
            personalPhone: snap.payload.doc.get("personalPhone"),
            selectedEmployeeStatus: snap.payload.doc.get("selectedEmployeeStatus"),
            isEmployee: snap.payload.doc.get("isEmployee"),
            isAdmin: snap.payload.doc.get("isAdmin"),
          };

          console.info("currentEmployee: ", currentEmployee);

          return currentEmployee;
        });
      });
      
                                                        
                                                        
  }

Этот метод перебирает каждый объект Employee[] и извлекается из FireStore и добавляет следующие два поля к исходному объекту:

id: snap.payload.doc.id,

и

completeName: snap.payload.doc.get("firstName") + " " + snap.payload.doc.get("surname"),

возврат измененного объекта.

Теперь проблема в том, что мое приложение сломалось, и в консоли браузера я получаю это сообщение об ошибке:

ERROR Error: InvalidPipeArgument: '[object Object]' for pipe 'AsyncPipe'
    at invalidPipeArgumentError (common.js:4154)
    at AsyncPipe._selectStrategy (common.js:4256)
    at AsyncPipe._subscribe (common.js:4246)
    at AsyncPipe.transform (common.js:4234)
    at Module.ɵɵpipeBind1 (core.js:24743)
    at EmployeeListComponent_Template (employee-list.component.html:31)
    at executeTemplate (core.js:7457)
    at refreshView (core.js:7326)
    at refreshComponent (core.js:8473)
    at refreshChildComponents (core.js:7132)

Я думаю, что проблема связана с тем, что в компоненте Angular, который вызывает мой сервисный метод:

// Load the list of all the employees:
async loadEmployeesList() {
    this.employeesList$ = await this.employeeService.getAllEmployees();
    console.info("employeesList$: ", this.employeesList$);
}

Я больше не получаю Observable, но получаю объект Subscriber (я вижу его с помощью console.info())

Как я могу исправить свой код, чтобы вернуть Observable, содержащий массив с измененными объектами?

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
0
0
83
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Подписка на поток возвращает его подписку.

const stream = of(1,2,3,4);
const subscription = stream.subscribe();

Вы подписываетесь, а затем возвращаете эту подписку

return stream.subscribe();

Похоже, что вы хотите сделать, это сопоставить каждый элемент в вашем потоке с новым элементом. Если это так, вы не должны subscribe, вы должны observable#map.

Что меня удивляет, так это то, что в вашем последнем вопросе вы действительно сделали map свое userObject, поэтому я не уверен, что послужило причиной изменения здесь при отображении массива.

Точно такой же подход работает, только теперь вы отображаете массив, а не объект. map(array => array.map(...)) довольно часто встречается в RxJS.

getAllEmployees(): Observable<Employee[]> { 
  //return <Observable<Employee[]>> this.firestore.collection('users',ref => ref.where('profileType', '!=', 'admin')).valueChanges(); 
    
  return <Observable<Employee[]>> <unknown>this.firestore.collection(
    'users', 
    ref => ref.where('isEmployee', '==', true)
  ).snapshotChanges().pipe(
    map(snaps => 
      snaps
        .map(snap => snap.payload.doc)
        .map(doc => ({
          id: doc.id,
          firstName: doc.get("firstName"),
          surname: doc.get("surname"),
          completeName: `${doc.get("firstName")} ${doc.get("surname")}`,
          placeOfBirth: doc.get("placeOfBirth"),
          socialSecurityCode: doc.get("socialSecurityCode"),
          birthDate: doc.get("birthDate"),
          companyEmail: doc.get("companyEmail"),
          personalEmail: doc.get("personalEmail"),
          companyPhone: doc.get("companyPhone"),
          personalPhone: doc.get("personalPhone"),
          selectedEmployeeStatus: doc.get("selectedEmployeeStatus"),
          isEmployee: doc.get("isEmployee"),
          isAdmin: doc.get("isAdmin")
        }))
    )
  );
}

Другие вопросы по теме