Две подписки прикованы к рефакторингу - PullRequest
0 голосов
/ 06 декабря 2018

Я пытаюсь реорганизовать приведенный ниже код с двумя подписками (одна в методе и одна в службе), и я не нахожу способ сделать это.

Я использую Акита для обработки моих состояний.Поэтому рекомендуется использовать подписки в службах, как указано в документации .

. Этот код предназначен для обработки случая денормализации: поле моего языка в коллекции User в коллекции Service сMongoDB.

Вот модели, которые я использую:

модель пользователя

export interface UserInfo {
  [...]
  services: ID[];
}

export interface User {
  _id: ID;
  [...]
  userInfo: Partial<UserInfo>;
}

сервисная модель

export interface ServiceInfo {
  [...]
  userFamilyName: string;
  userGivenName: string;
  userLanguages: Language[];
}

export interface Service {
  _id: ID;
  [...]
  serviceInfo: Partial<ServiceInfo>;
}

По моему методу

private addLanguage(languageForm: FormGroup) {

  [...]

  this.usersService.addLanguage(user).pipe(
    takeUntil(this.ngUnsubscribe)
  ).subscribe(
    (entity: User) => {
      if (entity.userInfo.services) {
        entity.userInfo.services.forEach(serviceId => {
          const service = createService({
            _id: serviceId,
            serviceInfo: {
              userLanguages: [language]
            }
          });

          this.servicesService.addLanguage(service); <--- have also a subscribe in its method
        })
      }

      languageForm.reset();
      this.onNavigateBack();
    }
  );
}

В сервисе

addLanguage(service: Service) {
  const url = `${this.servicesUrl}/${service._id}/languages`;
  const accessToken = this.authQuery.getSnapshot().accessToken;
  this.http.post<Service>(url, service, {
    headers: new HttpHeaders({
      'Content-Type': 'application/json',
      'Authorization': accessToken
    })
  }).subscribe(
    (entity: Service) => {
      if (this.servicesQuery.hasEntity(service._id)) {
        this.servicesStore.update(service._id, entity);
      }
    }
  );
}

Что я пробовал до сих пор:

this.usersService.addLanguage(user).pipe(
  filter((entity: User) => entity.userInfo.services !== undefined),
  switchMap((entity: User) => {
    entity.userInfo.services.forEach(serviceId => {
      const service = createService({
        _id: serviceId,
        serviceInfo: {
          userLanguages: [language]
        }
      });

      return this.servicesService.addLanguage(service);
    })
  }
);

Но я застрял из-за entity.userInfo.services.forEach.

Есть ли способ сделать это?

Спасибо за вашу помощь.

1 Ответ

0 голосов
/ 06 декабря 2018

Всякий раз, когда вы видите подписку внутри вашего сервиса, вероятно, что-то не так с кодом.Вам нужно будет использовать .tap() для выполнения побочных эффектов.Никогда не подписывайтесь на сервис, пусть компонент обрабатывает подписку.

В сервисе:

addLanguage(service: Service) {
    const url = `${this.servicesUrl}/${service._id}/languages`;
    const accessToken = this.authQuery.getSnapshot().accessToken;
    this.http.post<Service>(url, service, {
        headers: new HttpHeaders({
            'Content-Type': 'application/json',
            'Authorization': accessToken
        })
    })
        .pipe(
            tap((entity: Service) => {
                if (this.servicesQuery.hasEntity(service._id)) {
                    this.servicesStore.update(service._id, entity);
                }
            })
        );
}

В вашем компоненте вы можете легко добиться этого, используя filter() и * 1008.* с rxjs.Хитрость для forEach заключается в том, что вы используете .map() из встроенной функции массива Javascript.После того, как вы создали такой массив Observables, вы можете использовать forkJoin(), чтобы объединить их и запустить их параллельно:

В компоненте:

private addLanguage(languageForm: FormGroup) {
    this.usersService.addLanguage(user).pipe(
        takeUntil(this.ngUnsubscribe),
        //filter away the conditions  
        filter((entity: User) => entity.userInfo.services),
        switchMap((entity: User) => {
            //use .map() to create an array of services.
            let serviceObs$ = entity.UserInfo.services.map(serviceId =>
                this.servicesService.addLanguage(createService({
                    _id: serviceId,
                    serviceInfo: {
                        userLanguages: [language]
                    }
                })));
            //use forkJoin to combine all of them
            return forkJoin(serviceObs$);
        })
    ).subscribe(() => {
            languageForm.reset();
            this.onNavigateBack();
        }
    );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...