Цепные вызовы POST в Angular 8 - PullRequest
0 голосов
/ 10 марта 2020

Я провел массу исследований, прежде чем опубликовать этот вопрос, но 99,999% ссылок Google и StackOverflow о цепочке HTTP-вызовов в Angular относятся к запросам GET. Теоретически, они также должны применяться к запросам POST, но мой второй вызов POST НЕ выполняется; вызов в целом успешен, но companies/logo/{companyId} никогда не вызывается. Мой компонент имеет следующий код сохранения (где компания - это мой объект, а lo go - это ссылка на файл для компании lo go):

this.companyService.saveCompany(company, this.logo).subscribe(
  () => {
    this.companyForm.markAsPristine();
    this.snackBar.open('Company successfully saved.');
    this.router.navigate(['/companies']);
  },
  (err: HttpErrorResponse) => {
    if (err.status === 409) {
      this.snackBar.open('Company name already exists.');
    } else {
      this.snackBar.open('An error occurred on the server.');
    }

    this.isSaving = false;
  }
);

Вызов this.companyService.saveCompany выглядит следующим образом :

saveCompany(company: Company, logo?: File): Observable<number> {
  const saveCompany = company.id
    ? this.http.put<number>(`${this.baseUrl}companies`, company)
    : this.http.post<number>(`${this.baseUrl}companies`, company);

  if (logo) {
    const formData = new FormData();
    formData.append('logo', logo);

    saveCompany.pipe(
      mergeMap(companyId =>
        this.http.post<number>(
          `${this.baseUrl}companies/logo/${companyId}`,
          formData
        )
      )
    );
  }

  return saveCompany;
}

Компания успешно сохранена в моей базе данных с кодом сервера. Однако функция, определенная в mergeMap, НИКОГДА не вызывается; точка останова в Chrome Developer Tools никогда не срабатывает, мой API не вызывается, а lo go не сохраняется на сервере.

Я довольно новичок в попытках сделать что-то подобное цепочка в Rx JS, поэтому я уверен, что это что-то очевидное. Но опять же, Google пока ничего не показал.

Любая помощь здесь будет высоко оценена и полезна. Спасибо всем!

Ответы [ 2 ]

2 голосов
/ 10 марта 2020

Вы не переназначаете канал обратно переменной. Так что запускается только первый запрос.

Я бы также рекомендовал concatMap здесь. Это самый простой способ перехода к новой наблюдаемой.

saveCompany(company: Company, logo?: File): Observable<number> {
//<----- change from const to let
  let saveCompany = company.id
    ? this.http.put<number>(`${this.baseUrl}companies`, company)
    : this.http.post<number>(`${this.baseUrl}companies`, company);

  if (logo) {
    const formData = new FormData();
    formData.append('logo', logo);

//  <--- assign piped observable back to variable
    saveCompany = saveCompany.pipe(
      concatMap(companyId =>
        this.http.post<number>(
          `${this.baseUrl}companies/logo/${companyId}`,
          formData
        )
      )
    );
  }

  return saveCompany;
}

Упрощение ваших возвратов

Я обычно предпочитаю return как можно скорее, что сделало бы ошибку более ясной в это дело.

saveCompany(company: Company, logo?: File): Observable<number> {
  const saveCompany = company.id
    ? this.http.put<number>(`${this.baseUrl}companies`, company)
    : this.http.post<number>(`${this.baseUrl}companies`, company);

  // inverted check
  if (!logo) {
    return saveCompany;    
  }

  const formData = new FormData();
  formData.append('logo', logo);

  return saveCompany.pipe(
    concatMap(companyId =>
      this.http.post<number>(
        `${this.baseUrl}companies/logo/${companyId}`,
        formData
      )
    )
  );
}
1 голос
/ 10 марта 2020

Вместо объединения этих вызовов вы можете использовать Rx JS concatMap, чтобы ваш вызов выполнялся один за другим.

concatMap не будет подписываться на следующее Observable, пока не завершится текущий. Преимущество этого состоит в том, что поддерживается порядок, в котором излучаются Наблюдаемые.

проверьте эту статью среднего уровня для лучшего понимания Rx JS лестных стратегий .

...