Rxjs observable.pipe(take(1)) против toPromise

Недавно меня перевели в новый проект, который использует angular 6 в качестве внешнего интерфейса и spring для служб REST.

Проект находится в разработке уже 2 года, и я заметил, что почти все HTTP-запросы, сделанные с угловым HttpClient, затем направляются для получения фильтра из rxjs. Все REST API выдают только одно значение. Нет необходимости в ручной отмене и свойстве ленивости наблюдаемых.

Моя интуиция подсказывает, что использование toPromise() было бы лучшим способом кодирования.

о чем ты думаешь?

  //customer-service.ts
  constructor(private http: HttpClient) {

  }

  public getCustomers() {
     return http.get('/customers');
  }

  //component.ts
  public ngOnInit() {
      this.customerService.getCustomers().pipe(take(1)).subscribe((customers) => {
           //do some stuff
      })
  }

Мой предлагаемый подход:

  //customer-service.ts
  constructor(private http: HttpClient) {

  }

  public getCustomers() : Promise<Array<Customer>> {
     return http.get('/customers').toPromise();
  }

  //component.ts
  public ngOnInit() {
      this.customerService.getCustomers().then((customers: Array<Customer>) => {
         //do some stuff
      })
  }

Я думаю, что мой подход лучше, потому что он строго типизирован и чище.

Оба строго типизированы, а остальная часть Angular использует Rx, так что нет.

Roberto Zvjerković 29.05.2019 12:53

А как насчет читабельности? Вы бы предпочли .pipe(take(1)).subscribe() или .then() ? А как насчет эффективности с точки зрения скорости вычислений?

George Tarida 29.05.2019 13:18

Вы знаете, что тоже можете поставить pipe(take(1)) на службу? И вам даже не нужно take(1), потому что http observable завершается после отправки. Так что это просто subscribe против then. Но наблюдаемые гораздо чаще используются и более гибки.

Roberto Zvjerković 29.05.2019 13:28

Я понимаю. Еще один вопрос: если «http observable завершается после отправки», мне все еще нужно вызывать отмену подписки при подписке?

George Tarida 29.05.2019 13:36

Нет, не знаешь. Вы можете сохранить подписку и проверить .isUnsubscribed самостоятельно.

Roberto Zvjerković 29.05.2019 13:45

Мне действительно больше нравится версия toPromise(), потому что вы можете просто дождаться ответа, что приведет к, на мой взгляд, более чистому коду! В большинстве случаев вам не нужно передавать данные по конвейеру. И мне кажется странным обрабатывать каждый http-запрос как поток данных, который я вручную преобразовываю, чтобы он вел себя как обычное обещание, используя две дополнительные функции фреймворка. В большинстве случаев мне просто нужен ответ из одного или нескольких источников, и я преобразовываю их все в промисы и использую await или await Promise.all([...]). После этого я могу использовать map/reduce/filter все встроенные функции ES6.

denns 20.05.2021 17:42
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
7
6
3 676
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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


public getCustomers():Observable<Array<Customer>>  {
     return http.get<Array<Customer>>('/customers');
  }

  //component.ts
  public ngOnInit() {
      this.customerService.getCustomers()
      .pipe(take(1))
      .subscribe((customers: Array<Customer>) => {
       //do some stuff
       });
  }

  • Для HttpRequest с одним HttpResponse вы можете полагаться на обещать подход.
  • Но HttpRequest с множественным ответом, таким как прогресс/поток данные (блоб), использует подход Наблюдаемый.

Старайтесь использовать Observable как можно чаще, как только вы ознакомитесь с ним, вы не пойдете на другие варианты. Итак, попробуйте!

Вам даже не нужно вводить возвращаемый функцией тип, он будет выведен из http.

Roberto Zvjerković 29.05.2019 13:05

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

Veeraragavan 29.05.2019 13:07

Вы можете просто навести указатель мыши на метод, и он уже явно введен <Array<Customer>>, поэтому я не вижу смысла вводить его дважды.

Roberto Zvjerković 29.05.2019 13:10
Ответ принят как подходящий

Переход от наблюдаемых к обещаниям — это шаг назад.

Это как перейти с Porsche 911 на Fiat multipla.

Так что нет, вам не следует использовать toPromise(), и нет, ваш способ не «лучше» (это эго, приятель!)

I think that my approach is better because it is strongly typed and it's cleaner.

Ввод ответа HTTP зависит не от предположений или наблюдаемых, а от самого разработчика. А чистота — это вопрос перспективы, лично я ненавижу видеть toPromise()s.

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

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

В любом случае, если нет, и я полагаюсь только на предоставленный код, это будет правильный код:

public getCustomers() {
  return http.get<Customer[]>('/customers');
}

....

public ngOnInit() {
  this.customerService.getCustomers()
    .subscribe((customers) => {...})
}

Такой глупый уничижительный комментарий. Лучшая аналогия заключается в том, что если вам нужен только Fiat, но вы продолжаете ездить на Porsche, его обслуживание обойдется вам в 10 раз дороже, если вы не используете все функции Porsche. @ Джордж, рассмотрите возможность удаления принятого ответа. Превращение наблюдаемого объекта, который запускает только одно событие, в обещание, упрощает отслеживание вашего кода и работу с ним, вам не нужно беспокоиться о том, что обратный вызов вызывается несколько раз, и вам не нужно отписываться.

Juan Mendes 14.08.2020 15:56

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

Observables differentiate between chaining and subscription. Promises only have .then() clauses. This makes observables useful for creating complex transformation recipes to be used by other part of the system, without causing the work to be executed.

И разница между toPromise() и take(1) (или для краткого использования оператора first()) заключается в том, что take(1) завершается после того, как 1-е испущенное значение, в то время как toPromise ожидает последнего испущенного значения (ожидает, пока наблюдаемое значение Complete затем разрешает последнее сгенерированное значение).

Еще одно различие между наблюдаемыми и промисами, которое может вас заинтересовать, заключается в том, что подписки на Observable можно отменить, а промисы — нет. В качестве конкретного примера, скажем, ваш API /customers требует времени, но вам больше не нужны результаты, и вы переходите на другую страницу, отказ от подписки отменяет HTTP-запрос.

Я рекомендую продолжать использовать Observable.

Почему? Потому что позже будет проще:

  • построить предстоящую логику (такую ​​как сопоставление, фильтрация и т. д.) для запланированных функций
  • используйте код, поскольку смешивание двух подходов затрудняет чтение/запись

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

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