Вызов Angular API: Observable vs Promise

У меня есть эта служба, которая обращается к API, чтобы получить кучу описаний фильмов, и возвращает Observable:

getNowPlayingMovies$(page: number, country?: string): Observable<NowPlaying> {
    console.log(`${this.baseUrl}${this.now_playing}?${this.key}&region=${country || 'US'}&page=${page}`);
    return this.http.get<NowPlaying>(
      `${this.baseUrl}${this.now_playing}?${this.key}&region=${country || 'US'}&page=${page}`
    );
  }

В компоненте, который использует эту функцию выше, я называю ее изменением значения страницы каждый раз, чтобы я мог предложить пользователю разбиение на страницы в представлении компонента.

А это компонент, который вызывает службу:

getNowPlayingMovies(): void {
    this.nowPlayingService.getNowPlayingMovies$(this.page).subscribe((data) => {
      this.nowPlaying.push(
        ...data.results.filter((result) => result.backdrop_path)
      );
      if(!this.last_page){
        this.last_page = data.total_pages
        this.page++;
      } else if(this.page <= data.total_pages) {
        this.page++;
      }
      console.log(data);
      console.log(this.nowPlaying);
    });
  }

Я читал, что в Angular вы всегда должны пытаться работать с использованием Observable, а не Promises, но в таких сценариях я не вижу никаких преимуществ в подписке на ответ на вызов API.

Правильно ли преобразовать Observable в сервисе в Promise вот так?

getNowPlayingMovies$(page: number, country?: string): Promise<NowPlaying> {
    console.log(`${this.baseUrl}${this.now_playing}?${this.key}&region=${country || 'US'}&page=${page}`);
    return this.http.get<NowPlaying>(
      `${this.baseUrl}${this.now_playing}?${this.key}&region=${country || 'US'}&page=${page}`
    ).toPromise();
  }

Я изучаю Angular и работаю над этим, чтобы добавить его в свое портфолио, поэтому я хочу научиться делать это правильно и наилучшим образом.


person kiewlovsky    schedule 11.04.2021    source источник
comment
см. этот stackoverflow.com/questions /63462672/   -  person Moshezauros    schedule 11.04.2021
comment
Да работает в обе стороны, но я был бы признателен, если бы кто-то с большим опытом мог объяснить мне, в чем разница и какой вариант более подходит   -  person kiewlovsky    schedule 11.04.2021


Ответы (1)


Это не было бы неправильным, например: это сработает.

Вы теряете некоторые функции при переводе в промис, но самая важная из них обычно не имеет значения: по моему опыту, методы http не возвращают наблюдаемые, которые выдают несколько значений. Обратите внимание, что наблюдаемый API действительно оставляет эту возможность открытой. Вы можете покопаться в соответствующий источник, чтобы узнать больше.

Одна из причин, по которой многие ресурсы, вероятно, все еще предлагают вам работать с наблюдаемыми, заключается в том, что многие другие функции в Angular созданы или могут/должны быть созданы с помощью наблюдаемых. Подумайте о работе с реактивными формами, объединении нескольких HTTP-запросов, пользовательских событий и т. д. Если вы будете использовать наблюдаемые объекты для всех из них, RxJs предлагает вам мощные (но, возможно, сложные и/или запутанные) способы их объединения. Рассмотрим, например:

  • наблюдаемый http.get для получения фильмов
  • пользователь, вводящий в поле ввода, возможно, piped через debounce
  • комбинируя его с http.post для запроса альтернативных фильмов
  • combineLatest все это и, возможно, pipe через debounce или distinctUntilChanged для обновления пользовательского интерфейса в нужное время
  • и т.п.

Построение всех этих взаимодействий при преобразовании вызовов http в Promise<T> сразу потребует дополнительной работы и может даже показаться неидиоматичным.

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

person Jeroen    schedule 11.04.2021
comment
Спасибо Jeroen, это то объяснение, которое я искал. Итак, следуя примеру, который я опубликовал, возможно, лучший вариант — вернуть наблюдаемое из моего сервиса, но, может быть, в компоненте использовать оператор канала для преобразования его в обещание? Потому что единственное, что я думаю при подписке, это сохранить значение ответа в переменной. - person kiewlovsky; 11.04.2021
comment
Да. Хотя я не уверен, почему ваш компонент захочет преобразовать его в обещание? Компонент может просто subscribe получить результат и использовать его, или вы можете использовать канал async (который обрабатывает подписку/отмену подписки за вас) для непосредственного просмотра фильмов в компоненте. - person Jeroen; 12.04.2021