В чем разница между обещаниями и наблюдаемыми?

1399

Какая разница между Promiseи Observableв Angular?

Пример каждого из них поможет понять оба случая. В каком сценарии мы можем использовать каждый случай?

Рохит
источник
23
Я хотел бы предложить вам прочитать этот пост; Angular2 обещание против наблюдаемого
erolkaya84
4
в более простых терминах angular-2-training-book.rangle.io/handout/observables/...
Пардип Jain
3
Любой, кто читает эти вопросы и ответы - как кто-то, кто связан с обоими мирами от сопровождающего, докладчика и давнего пользователя PoV, призываю вас прочитать официальные документы RxJS и документацию MDN по обещаниям. Лично я нахожу здесь ответы полностью вводящими в заблуждение и неправильными и верю, что они, хотя и с благими намерениями людей, которые пытаются помочь, очень вредны.
Бенджамин Грюнбаум
1
Я хотел бы предложить вам прочитать этот угловой официальный документ angular.io/guide/comparing-observables
fgul,
И именно поэтому ссылки считаются неприемлемыми в качестве ответов.
Дэйв

Ответы:

1552

обещание

PromiseОбрабатывает одно событие , когда завершается асинхронной операции или терпит неудачу.

Примечание: есть Promiseбиблиотеки, которые поддерживают отмену, но ES6 Promiseпока нет.

наблюдаемый

An Observableподобна Stream(во многих языках) и позволяет передавать ноль или более событий, когда обратный вызов вызывается для каждого события.

Часто Observableпредпочтительнее, Promiseпотому что он предоставляет функции Promiseи многое другое. При Observableэтом не имеет значения, хотите ли вы обрабатывать 0, 1 или несколько событий. Вы можете использовать один и тот же API в каждом случае.

Observableтакже имеет преимущество перед Promiseбыть аннулированы . Если результат запроса HTTP на сервер или какой - либо другой операции дорогой асинхронном больше не требуется, то Subscriptionиз Observableпозволяет отменить подписку, в то время как Promiseв конечном итоге вызвать успех или сбой обратного вызова , даже если вам не нужно уведомление или результат, который он дает больше.

Наблюдаемое предоставляет операторам , как map, forEach, reduce, ... похожие на массив

Есть также мощные операторы, такие как retry(), или replay(), ... которые часто очень удобны.

Гюнтер Цохбауэр
источник
180
Так есть ли веская причина использовать Promise вместо Observable в случае с одним обратным вызовом или же там должны использоваться Observable, поскольку они тоже могут работать таким образом? По сути, это хорошая практика "Наблюдать за всеми вещами" или Promise все еще имеет свое место?
Джош Вертс
75
Если вы хотите использовать реактивный стиль, просто используйте наблюдаемые везде. Если у вас есть только наблюдаемые, вы можете легко составить. Если вы смешаете их, это уже не так чисто. Если вы не заботитесь о реактивном стиле, вы можете использовать обещание для отдельных событий, когда вас не интересует возможность отмены и наблюдаемые потоки событий.
Гюнтер Цохбауэр
35
@ GünterZöchbauer Эй, у меня нет аргументов против Observables или функционального программирования. Я просто заявляю, что считаю, что люди, работающие с Observables в основном через http в NG2, не имеют никакой реальной причины использовать Observables вместо Promises для выполнения вызовов. Они не теряют ничего практического, используя обещания. Операторы debounce и retry не имеют значения - вы можете дебатировать с помощью ng-debounce, и, если ожидается, что вызов потерпит неудачу, обычно возникает проблема с кодом. Единственный раз, когда мне нужно было работать с повторными вызовами, был запрос нестабильных сторонних API для HVT.
VSO
92
Но, пожалуйста, не забывайте, что Promise, наряду с async/, awaitваш код снова становится плоским! В большинстве ситуаций и в проектах, которые не имеют отношения к ракетостроению, нет необходимости писать эти ужасные вложенные функции с излишне сложными цепочками методов. Вы можете использовать async/ awaitсегодня с транспиляторами, например TypeScript, и писать реальный понятный для человека плоский код без всякого rxjsшаблона. Вы, вероятно, все еще будете нуждаться rxjsиногда в избранных ситуациях, потому что у этого действительно есть много вещей, чтобы предложить.
evilkos
15
Этот ответ вводит в заблуждение, наблюдаемое не похоже на поток, оно похоже на функцию, которая возвращает поток .
Бенджамин Грюнбаум
336

И то, Promisesи другое Observablesпредоставляет нам абстракции, которые помогают нам справляться с асинхронной природой наших приложений. Разница между ними была четко указана @ Günter и @Relu.

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

Спасибо @Christoph Burgdorf за отличную статью


Angular использует Rx.js Observables вместо обещаний иметь дело с HTTP.

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

  • Мы не хотим попадать на конечную точку сервера каждый раз, когда пользователь нажимает клавишу, он должен заполнять их потоком HTTPзапросов. По сути, мы хотим нажать на него только после того, как пользователь перестал печатать вместо каждого нажатия клавиши.
  • Не нажимайте конечную точку поиска с теми же параметрами запроса для последующих запросов.
  • Разберитесь с неупорядоченными ответами. Когда у нас есть несколько запросов одновременно, мы должны учитывать случаи, когда они возвращаются в неожиданном порядке. Представьте, что мы сначала печатаем компьютер , останавливаемся, запрос отправляется, мы набираем машину , останавливаем запрос отправляем. Теперь у нас есть два запроса в полете. К сожалению, запрос, содержащий результаты для компьютера, возвращается после запроса, который содержит результаты для автомобиля .

Демо будет просто состоять из двух файлов: app.tsи wikipedia-service.ts. В сценарии реального мира мы, скорее всего, разделим вещи дальше.


Ниже приведена реализация на основе Promise , которая не обрабатывает ни один из описанных крайних случаев.

wikipedia-service.ts

import { Injectable } from '@angular/core';
import { URLSearchParams, Jsonp } from '@angular/http';

@Injectable()
export class WikipediaService {
  constructor(private jsonp: Jsonp) {}

  search (term: string) {
    var search = new URLSearchParams()
    search.set('action', 'opensearch');
    search.set('search', term);
    search.set('format', 'json');
    return this.jsonp
                .get('http://en.wikipedia.org/w/api.php?callback=JSONP_CALLBACK', { search })
                .toPromise()
                .then((response) => response.json()[1]);
  }
}

Мы внедряем Jsonpсервис для GETзапроса API-интерфейса Wikipedia с заданным поисковым термином. Обратите внимание, что мы звоним toPromise, чтобы получить от а Observable<Response>до Promise<Response>. В конце концов, в Promise<Array<string>>качестве возвращаемого типа нашего метода поиска получим.

app.ts

// check the plnkr for the full list of imports
import {...} from '...';

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Wikipedia Search</h2>
      <input #term type="text" (keyup)="search(term.value)">
      <ul>
        <li *ngFor="let item of items">{{item}}</li>
      </ul>
    </div>
  `
})
export class AppComponent {
  items: Array<string>;

  constructor(private wikipediaService: WikipediaService) {}

  search(term) {
    this.wikipediaService.search(term)
                         .then(items => this.items = items);
  }
}

Здесь тоже нет ничего удивительного. Мы внедряем наш WikipediaServiceи выставляем его функциональность через шаблон поиска в шаблон. Шаблон просто привязывается к keyup и звонкам search(term.value).

Мы разворачиваем результат Обещания, который возвращает метод поиска в WikipediaService, и выставляем его в виде простого массива строк в шаблоне, чтобы можно было *ngForвыполнить цикл по нему и создать для нас список.

Посмотрите пример реализации на основе Promise на Plunker


Где наблюдаемые действительно сияют

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

Чтобы раскрыть такие сверхспособности, нам сначала нужно получить выражение Observable<string>, содержащее поисковый термин, который вводит пользователь. Вместо ручной привязки к событию keyup мы можем воспользоваться formControlдирективой Angular . Чтобы использовать эту директиву, нам сначала нужно импортировать ReactiveFormsModuleв наш модуль приложения.

app.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { JsonpModule } from '@angular/http';
import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [BrowserModule, JsonpModule, ReactiveFormsModule]
  declarations: [AppComponent],
  bootstrap: [AppComponent]
})
export class AppModule {}

После импорта мы можем использовать formControl из нашего шаблона и установить для него имя «term».

<input type="text" [formControl]="term"/>

В нашем компоненте мы создаем экземпляр FormControlfrom @angular/formи выставляем его как поле под именем term в нашем компоненте.

За кулисами термин автоматически предоставляет Observable<string>свойство as, на valueChangesкоторое мы можем подписаться. Теперь, когда у нас есть Observable<string>, преодоление пользовательского ввода так же просто, как вызов debounceTime(400)нашего Observable. Это вернет новое значение, Observable<string>которое будет выдавать новое значение только в том случае, если новые значения не поступали в течение 400 мс.

export class App {
  items: Array<string>;
  term = new FormControl();
  constructor(private wikipediaService: WikipediaService) {
    this.term.valueChanges
              .debounceTime(400)        // wait for 400ms pause in events
              .distinctUntilChanged()   // ignore if next search term is same as previous
              .subscribe(term => this.wikipediaService.search(term).then(items => this.items = items));
  }
}

Было бы напрасной тратой ресурсов на отправку еще одного запроса по поисковому запросу, для которого наше приложение уже показывает результаты. Все, что нам нужно сделать для достижения желаемого поведения, это вызвать distinctUntilChangedоператора сразу после того, как мыdebounceTime(400)

Смотрите пример реализации Observable на Plunker

Чтобы разобраться с неупорядоченными ответами, ознакомьтесь с полной статьей http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html.

Поскольку я использую Http в Angular, я согласен, что в обычных случаях использования нет большой разницы при использовании Observable over Promise. Ни одно из преимуществ на самом деле не актуально здесь на практике. Надеюсь, что я смогу увидеть какой-нибудь продвинутый вариант использования в будущем :)


Учить больше

trungk18
источник
31
Я не совсем согласен с решением превратить сервис Http в Observable. Каждое объяснение, которое я слышу, опирается на один и тот же пример: поиск по термину. Но это касается обработки событий браузера. Я хотел бы услышать, каково преимущество в его применении при работе с асинхронными http-запросами.
Алекс Поллан
1
Было ли решение случайно избежать смешанных моделей?
Алекс Поллан
6
@AlexPollan, на самом деле есть хорошее объяснение преимуществ службы http, возвращающей наблюдаемое в этом подкасте с Беном Лешем: devchat.tv/js-jabber/… . В конечном счете, основным преимуществом является то, что вы можете отменить наблюдаемое, и сценарий использования для этого, описанный в ссылке выше - хотя и немного надуманный, - это если вы вызываете несколько apis и заботитесь только о первом ответе, независимо от того, какой из apis, который вы вызывали, сначала возвращается к вам, затем вы можете отменить запросы к другим.
nikolasleblanc
2
@nikolasleblanc, я уверен, что вы можете использовать $ q.race () для этого?
jameslouiz
2
@AlexPollan, преимущество в том, что служба HTTP на основе Observable позволяет легко отменять HTTP-запросы в середине полета. Условие состязания в ответе trungk18 можно решить, просто отписавшись от HTTP, наблюдаемого перед выполнением следующего запроса. RXJS switchMap может использоваться для HTTP-запросов, запускаемых другой наблюдаемой (например, valueChanges). Для автономных HTTP-наблюдений вы можете отписаться и повторно подписаться вручную.
Stevethemacguy
236

И Promises, и Observables помогут нам работать с асинхронными функциями в JavaScript. Они очень похожи во многих случаях, однако, между ними все еще есть некоторые различия, обещания - это значения, которые будут разрешаться asynchronousтакими способами, как http- вызовы. С другой стороны, наблюдаемые имеют дело с последовательностью асинхронных событий . Основные различия между ними перечислены ниже:

обещаю:

  • с одним трубопроводом
  • обычно используется только с асинхронным возвратом данных
  • не легко отменить

наблюдаемый:

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

Кроме того, я создал графическое изображение для вас ниже, чтобы визуально показать различия:

Обещания и наблюдаемые изображения

Алиреза
источник
4
обещание "не легко отменить", можно ли их отменить?
Пардип Джейн
10
да, есть также способ отменить их ... некоторые люди используют библиотеки bluebird или сторонние библиотеки ... также используя библиотеку Q в Angular, есть способы отменить это ... но, как я сказал, не очень удобно
Alireza
Наличие одного трубопровода иногда имеет преимущество, напр. в APP_INITIALIZER, если у вас несколько конвейеров, он никогда не может завершиться иногда или завершиться несколько раз.
windmaomao
6
отмена это Promiseнеправильный способ думать о том, как обещания. PromiseНесет ответственность» , это только к успеху ручки или отказу в совместимом способе асинхронного .. Если вы хотите , чтобы отменить запрос HTTP вы отменить запрос, а не обещание, и сделать результат отмены либо выполнить или отклонить обещание. jsfiddle.net/greggman/ea0yhd4p
мужчина
2
@ gman Точно. Обещание просто представляет некоторую будущую ценность . Он не представляет операцию, которая генерирует значение . Вы не можете отменить значение. Вы не можете повторить значение. Это просто ценность. Он может присутствовать или не присутствовать , и может никогда не существовать, потому что произошло исключение, но это так.
Йона Апплетри
75

обещания

  1. Определение: помогает выполнять функции асинхронно и использовать их возвращаемые значения (или исключения), но только один раз при выполнении.
  2. Не ленивый
  3. Не подлежит отмене (есть библиотеки Promise, которые поддерживают отмену, но ES6 Promise пока не поддерживает). Два возможных решения
    • отклонять
    • Разрешить
  4. Невозможно повторить (Promises должен иметь доступ к исходной функции, которая вернула обещание с возможностью повторной попытки, что является плохой практикой)

Наблюдаемые

  1. Определение: Помогает вам выполнять функции асинхронно и использовать их возвращаемые значения в непрерывной последовательности ( несколько раз ) при выполнении.
  2. По умолчанию это Lazy, так как он генерирует значения по ходу времени.
  3. Имеет много операторов, что упрощает кодирование.
  4. Один оператор повторной попытки может быть использован для повторной попытки, когда это необходимо, также, если нам нужно повторить наблюдаемое, основываясь на некоторых условиях, повторная попытка при использовании.

    Примечание : список операторов вместе с их интерактивными диаграммами доступен здесь на RxMarbles.com

Аравиндом
источник
67

В ответах отсутствует один недостаток Observables. Обещания позволяют использовать функции ES7 async / await. С их помощью вы можете написать асинхронный код, как если бы это был синхронный вызов функции, поэтому вам больше не нужны обратные вызовы. Единственная возможность для Observables сделать это - преобразовать их в Обещания. Но когда вы конвертируете их в Promises, вы можете снова получить только одно возвращаемое значение:

async function getData(){
    const data = await observable.first().toPromise();
    //do stuff with 'data' (no callback function needed)
}

Дальнейшее чтение: Как я могу «ждать» на Rx Observable?

Besserwisser
источник
21
Также удивило, почему никто не указал на эту убийственную привилегию Promises - простота и прозрачность благодаря async / await. Я переключился на Обещания только для возможности написания простого кода. Простая бизнес-логика и код взаимодействия с пользовательским интерфейсом не должны выглядеть как ракетостроение и быть загрязненными вложенным адом реактивных расширений. Кроме того, async / await не только в будущем, вы можете использовать его в общедоступных производственных приложениях, теперь использующих транспортеры. Я использую TypeScript 2.3, и он потрясающий, как настоящий язык.
evilkos
Хорошо, но мы думаем реактивно и все с RxOperators, может быть, это не убийственная особенность
JorgeTovar
37

Обещания и Observables обрабатывают только асинхронный вызов.

Вот различия между ними:

наблюдаемый

  1. Выдает несколько значений за период времени
  2. Не вызывается, пока мы не подпишемся на Observable
  3. Можно отменить с помощью метода unsubscribe ()
  4. Предоставляет карту, forEach, фильтрует, уменьшает, повторяет и повторяет, когда операторы

обещание

  1. Выдает только одно значение за раз

  2. Звонит в сервисы без .then и .catch

  3. Не может быть отменено

  4. Не предоставляет никаких операторов

судхир нунна
источник
2
Что именно вы подразумеваете под обещанием, выдает только одно значение, в то время как наблюдаемое излучает несколько
Абель
2
Обещание не имеет значения вообще - обещание - это значение с течением времени. Обещание многоадресно передает это значение нескольким подписчикам - если вы держите обещание, у вас уже есть значение. Наблюдаемое похоже на функцию , подписка на которую вызывает действие.
Бенджамин Грюнбаум
1
@BenjaminGruenbaum Тем не менее, я не получил среднее число подписчиков, не могли бы вы предоставить ссылку или пример. Спасибо
Дипак Патидар
2
observable1.subscribe (subscriber1), observable1.subscribe (subscriber2) - это вызывает функцию несколько раз.
Бенджамин Грюнбаум
2
Пожалуйста, отредактируйте свой пост и покажите реальный текст вместо скриншотов. Другие не могут копировать и вставлять из ваших изображений, а также не могут помочь вам исправить многие грамматические ошибки. Смотрите здесь для деталей. Спасибо.
Пан
26

Несмотря на то, что этот ответ запоздал, я суммировал различия ниже,

Наблюдаемое:

  1. Наблюдаемый это просто, functionкоторый принимает an observerи возвращает function Observer: an object with next, error.
  2. Наблюдатель позволяет subscribe/unsubscribeсвоему потоку данных передавать следующее значение наблюдателю, notifyнаблюдателю errorsи информировать наблюдателя оstream completion
  3. Observer предоставляет сообщения об function to handle next valueошибках и конце потока (события пользовательского интерфейса, ответы http, данные с веб-сокетами).
  4. Работает со multiple valuesвременем
  5. Это cancel-able/retry-ableи поддерживает операторов, таких как map,filter,reduceи т. Д.
  6. Создание Observable может быть - Observable.create()- возвращает Observable, который может вызывать методы - Observer Observable.from()- преобразует массив или итерируется в - Observable Observable.fromEvent()- преобразует событие в Observable - Observable.fromPromise()- преобразует Promise в Observable - Observable.range()- возвращает последовательность целых чисел в указанном диапазоне

Обещание :

  1. Обещание представляет собой задачу, которая закончится в будущем;

  2. Обещания становятся resolved by a value;

  3. Обещания отклоняются исключениями;

  4. Нет cancellableи возвращаетсяa single value

  5. Обещание разоблачить функцию (then)

    -тогда вернет новый promise;

    -позволяет для attachmentтого что будет выполнено на основании state;

    - handlersэто guaranteedвыполнить в order attached;

Sajeetharan
источник
20

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

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

Единственный способ успешно заполнить все переменные выпадающего меню - это вызвать службу таким образом, чтобы предотвратить обработку нового запроса до тех пор, пока последний запрос не будет завершен, и механизм Promise / .then хорошо решил проблему.

  fetchValueList(listCode): Promise<any> {
      return this.dataSvc.getValueList(listCode, this.stateSvc.currentContext, this.stateSvc.currentLanguageCode)
          .map(response => response.json())
          .toPromise();
  }

  initializeDropDowns() {
      this.fetchValueList('First-Val-List')
          .then(data => {
              this.firstValList = data;
              return this.fetchValueList('Second-Val-List')
          }).then(data => {
              this.secondValList = data;
              return this.fetchValueList('Third-Val-List')
          }).then(data => {
              this.thirdValList = data;
          })  }

Я определил функции в компоненте, а затем вызвал initializeDropDowns () в ngOnInit.

Функция fetchValueList возвращает Promise, поэтому первый вызов передает первый listCode, и когда Promise разрешается, возвращаемое значение находится в переменной данных в блоке .then, где мы можем присвоить его переменной this.firstValList. Поскольку функция вернула данные, мы знаем, что служба завершена, и ее можно снова вызвать с помощью второго listCode, возвращаемое значение находится в переменной data в следующем блоке .then, и мы присваиваем его переменной this.secondValList.

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

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

Стивен Р. Смит
источник
3
Это, конечно, также возможно с наблюдаемыми (высшего порядка). Например, вы можете использовать scan()для создания потока последовательных наблюдаемых. Тем не менее, ваш подход может быть более явным и более простым для понимания.
lex82
1
Вы можете заменить «then» на «switchMap» и сделать то же самое с observables.
Доктор К.
1
Проблема с switchMap, насколько я понимаю, состоит в том, что он будет запускать все запросы параллельно и ждать, пока они все не вернутся, а затем вернуть значения вызывающей функции, тогда как в моей ситуации у меня есть один сервер, который я не могу звоните несколько раз параллельно (так как сервер будет отбрасывать незавершенные запросы при поступлении новых), поэтому мне нужно было убедиться, что каждый вызов службы базы данных завершен, прежде чем начинать новый вызов, и тогда Promise / казался лучшим и возможно, единственный способ решить это.
Стивен Р. Смит
1
Почему вы не использовали цепочку объединенной карты? Насколько я понял ваш код, он довольно прост и делает работу так же хорошо, как ваш пример. @ StephenR.Smith
руда
1
@Ore Можете ли вы добавить пример кода для решения той же проблемы, что и другой ответ? Будет хорошей ссылкой и может стать хорошей возможностью рефакторинга в будущем. Требование состоит в том, что любой код не может параллельно вызывать внутреннюю службу, он должен вызывать, ждать возвращаемого значения и вызывать снова.
Стивен Р. Смит
20

Я считаю, что все остальные ответы должны очистить ваши сомнения. Тем не менее, я просто хотел добавить, что наблюдаемые основаны на функциональном программировании, и я нахожу очень полезными функции, которые идут вместе с ним, такие как map, flatmap, lower, zip. Согласованность, которую обеспечивает сеть, особенно когда она зависит от запросов API, является серьезным улучшением.

Я настоятельно рекомендую эту документацию , поскольку это официальная документация о реактиве X, и я считаю ее наиболее понятной.

Если вы хотите получить доступ к наблюдаемым, я бы предложил этот пост из трех частей: http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1/

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

Марк Перес
источник
18

Promise:

  • Предоставить единую будущую стоимость;
  • Не ленивый;
  • Не подлежит отмене;

Наблюдаемое:

  • Выдает несколько значений с течением времени;
  • Ленивый;
  • Cancellable;
  • Поддерживает карту, фильтр, уменьшить и аналогичные операторы

При желании вы можете использовать обещания вместо наблюдаемых при вызове HTTP в Angular.

Иосуа Сипос
источник
16

Обзор:

  • И Promises, и Observables помогают нам справляться с асинхронными операциями. Они могут вызывать определенные обратные вызовы, когда эти асинхронные операции выполнены.
  • Обещание может обрабатывать только одно событие, Observables предназначены для потоков событий с течением времени.
  • Обещания не могут быть отменены, как только они ожидают
  • Данные Observables Emit могут быть преобразованы с помощью операторов

Вы всегда можете использовать наблюдаемое для работы с асинхронным поведением, так как наблюдаемое обладает всеми функциями, которые предлагает обещание (+ дополнительно). Однако иногда эта дополнительная функциональность, которую предлагают Observables, не нужна. Тогда было бы лишними издержками импортировать библиотеку, чтобы она могла их использовать.

Когда использовать Обещания:

Используйте обещания, когда у вас есть одна асинхронная операция, для которой вы хотите обработать результат. Например:

var promise = new Promise((resolve, reject) => {
  // do something once, possibly async
  // code inside the Promise constructor callback is getting executed synchronously

  if (/* everything turned out fine */) {
    resolve("Stuff worked!");
  }
  else {
    reject(Error("It broke"));
  }
});

//after the promise is resolved or rejected we can call .then or .catch method on it

promise.then((val) => console.log(val))      // logs the resolve argument
       .catch((val) => console.log(val));    // logs the reject argument

Таким образом, обещание выполняет некоторый код, где оно либо разрешает, либо отклоняет. Если резолвить или отклонить называются обещание переходит из отложенного состояния либо в разрешенном или отвергнуто государство. Когда состояние обещания разрешается, then()вызывается метод. Когда состояние обещания отклоняется, catch()вызывается метод.

Когда использовать Observables:

Используйте Observables, когда есть поток (данных) с течением времени, который вам нужно обработать. Поток - это последовательность элементов данных, которые становятся доступными с течением времени . Примеры потоков:

  1. Пользовательские события, например, щелчки или нажатия клавиш. Пользователь генерирует события (данные) с течением времени.
  2. Websockets: после того, как клиент установил соединение WebSocket с сервером, он со временем передает данные.

В самой Наблюдаемой задается, когда произошло следующее событие , когда произошла ошибка , или когда Наблюдаемая завершена . Затем мы можем подписаться на эту наблюдаемую, которая активирует ее, и в этой подписке мы можем передать 3 обратных вызова (не всегда нужно передавать все). Один обратный вызов для выполнения, один обратный вызов для ошибки и один обратный вызов для завершения. Например:

const observable = Rx.Observable.create(observer => {
  // create a single value and complete
  observer.onNext(1);
  observer.onCompleted();
});

source.subscribe(
  x => console.log('onNext: %s', x),   //  success callback
  e => console.log('onError: %s', e),  //  error callback
  () => console.log('onCompleted')     //  completion callback
 );

// first we log: onNext: 1
//  then we log: onCompleted

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

Виллем ван дер Веен
источник
9

Обещание - предоставить единую будущую стоимость. Не ленивый . Не отменяется. Он либо отклонит, либо разрешит.

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

Гаджендер Сингх
источник
8

Обещание против наблюдаемого сходства в первую очередь

  1. Оба использовали для обработки асинхронного кода.
  2. Пожалуйста, посмотрите на пример обещания. Конструктор Promise передает справочную функцию разрешения, которая будет вызываться при вызове с некоторым значением после выполнения некоторой асинхронной задачи.

const promise = new Promise(resolve => {
  setTimeout(() => {
    resolve("Hello from a Promise!");
  }, 2000);
});

promise.then(value => console.log(value));

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

  2. Таким образом, обе обрабатывают асинхронные задачи. Теперь посмотрим на разницу.


const observable = new Observable(observer => {
  setTimeout(() => {
    observer.next('Hello from a Observable!');
  }, 2000);
});

observable.subscribe(value => console.log(value));

Обещание против наблюдаемой разницы

обещание

  1. Он разрешает или отклоняет одно значение и может одновременно обрабатывать одно значение асинхронной задачи.
  2. Обещание, однажды разрешившее асинхронное значение, которое оно завершает, больше не может быть использовано. Это только одноразовое использование, и здесь оно не выполняется.
  3. Не подлежит отмене
  4. Нет поддержки rxjs для операторов.

наблюдаемый

  1. способность выдавать несколько асинхронных значений.
  2. Используется для обработки потока событий или значений. Предположим, у вас есть массив из множества задач или значений, и вы хотите, чтобы каждый раз, когда значение вставлялось в него, оно должно обрабатываться автоматически. Каждый раз, когда вы помещаете значение в этот массив, все его подписчики получат последнее значение автоматически.
  3. Observables полезны для наблюдения изменений входных данных, повторяющихся интервалов, широковещательных значений для всех дочерних компонентов, push-уведомлений веб-сокетов и т. Д.
  4. Может быть отменено с помощью метода отписки в любое время.
  5. Еще одна хорошая новость, которая обещает поддержку операторов rxjs. У вас есть много операторов конвейера, в основном, отображающих, фильтрующих, switchMap, Объединение последних и т. Д. Для преобразования наблюдаемых данных перед подпиской.

введите описание изображения здесь


Рамеш Шарма
источник
6

И Promises, и Observables помогают нам справляться с асинхронными операциями. Они могут вызывать определенные обратные вызовы, когда эти асинхронные операции выполнены.

Angular использует Observables из RxJS вместо обещаний иметь дело с HTTP

Below are some important differences in promises & Observables.

разница между обещаниями и наблюдаемыми

Srikrushna
источник
1
Представленные в таблице данные кажутся неверными, название следует поменять местами
Derrick.X
1
Пожалуйста, отредактируйте свой пост и покажите фактический контент в виде текста вместо скриншотов. Другие не могут копировать и вставлять из ваших изображений. Смотрите здесь для деталей. Спасибо.
Пан
6

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

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

Часто наблюдаемый предпочтительнее Обещания, поскольку он дает основные моменты Обещания и многое другое. С Observable не имеет значения, нужно ли вам обрабатывать 0, 1 или различные события. Вы можете использовать аналогичный API для каждого случая.

Обещание: обещание испускает одно значение

Например:

const numberPromise = new Promise((resolve) => {
    resolve(5);
    resolve(10);
});

numberPromise.then(value => console.log(value));
// still prints only 5

Наблюдаемый: излучает несколько значений за период времени

Например:

  const numberObservable = new Observable((observer) => {
        observer.next(5);
        observer.next(10);
    });

numberObservable.subscribe(value => console.log(value));
// prints 5 and 10

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

Promise:

  • Обещание не ленивый
  • Обещание не может быть отменено

Наблюдаемое:

  • Наблюдаемый ленивый. «Наблюдаемый» медленный. Это не называется, пока мы не подписаны на это.
  • Observable можно отменить с помощью метода unsubscribe ()
  • Дополнение Observable предоставляет множество мощных операторов, таких как map, foreach, filter, Reduce, Retry, RetryWhen и т. Д.

Угловые обещания против наблюдаемых

декабрь
источник
5

Promise выдает одно значение, а Observable - несколько значений. Таким образом, при обработке HTTP-запроса Promise может управлять одним ответом на один и тот же запрос, но что, если на один и тот же запрос существует несколько ответов, мы должны использовать Observable. Да, Observable может обрабатывать несколько ответов на один и тот же запрос.

обещание

const promise = new Promise((data) =>
{ data(1);
  data(2);
  data(3); })
.then(element => console.log(‘Promise ‘ + element));

Вывод

Promise 1

наблюдаемый

const observable = new Observable((data) => {
data.next(1);
data.next(2);
data.next(3);
}).subscribe(element => console.log('Observable ' + element));

Вывод

Observable 1
Observable 2
Observable 3
Йогеш Вагмаре
источник
3

Ниже приведены некоторые важные различия в обещаниях и наблюдаемых.

обещание

  • Выдает только одно значение
  • Не подлежит отмене
  • Не подлежит разделению
  • Всегда асинхронный

наблюдаемый

  • Выдает несколько значений
  • Выполняется только когда он вызывается или кто-то подписывается
  • Может быть отменено
  • Может быть разделено и подписано этим общим значением несколькими подписчиками. И все подписчики выполнят в один момент времени.
  • возможно асинхронный

Для лучшего понимания обратитесь к https://stackblitz.com/edit/observable-vs-promises.

Бикрам
источник
3

Я вижу, что многие люди используют аргумент, что Observable являются «отменяемыми», но довольно просто сделать Promise «отменяемыми»

function cancellablePromise(body) {
  let resolve, reject;
  const promise = new Promise((res, rej) => {
    resolve = res; reject = rej;
    body(resolve, reject)
  })
  promise.resolve = resolve;
  promise.reject = reject;
  return promise
}

// Example 1: Reject a promise prematurely
const p1 = cancellablePromise((resolve, reject) => {
  setTimeout(() => resolve('10', 100))
})

p1.then(value => alert(value)).catch(err => console.error(err))
p1.reject(new Error('denied')) // expect an error in the console

// Example: Resolve a promise prematurely
const p2 = cancellablePromise((resolve, reject) => {
  setTimeout(() => resolve('blop'), 100)
})

p2.then(value => alert(value)).catch(err => console.error(err))
p2.resolve(200) // expect an alert with 200

Батист Билер
источник
2

Короткий ответ :

Наблюдаемый является лучше , она имеет все Обещания функции плюс дополнительные функции.


Длинный ответ:

Обещания:

  • Одноразовое использование «Вернуть данные один раз»
  • Нет отмены
  • Один слушатель
  • Нет поддержки сокета один слушатель

Наблюдаемое:

  • Возвращать данные много раз при изменении данных
  • Поддержка отмены
  • Гнездо поддержки
  • Поддержка многих слушателей и уведомлять их при изменении данных
  • Поддержка карты, фильтрация, уменьшение
Амр Ибрагим
источник
Я не думаю, что вы можете сказать, что Observables объективно лучше. Есть несколько недостатков в Observables, отмеченных в различных ответах здесь. То, что выделяет меня, - это сложность Observable, и то, что они не работают напрямую с await / async. Я лично считаю, что с ними действительно трудно работать, потому что вы не можете определить поведение Observable при его использовании - вы должны посмотреть на код, который его сгенерировал. В то время как с Обещанием вы точно знаете, как они работают, всегда. Например, иногда подписка на Observable имеет побочные эффекты (например, запрос http), но иногда нет.
Йона Апплетри
Для угловых это зависит от вашего случая. в большинстве случаев мы будем работать со службами и некоторыми данными, которые будут влиять на разные места, сокеты, отмену, отображение, фильтрацию и уменьшение. так будет лучше в тех случаях, когда обещания не поддерживают их. так что опять это зависит от вашего случая
Амр Ибрагим
2

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

Например, любое обнаружение изменений вручную на уничтоженном компоненте вызовет исключение:

ngOnInit() {
  // promise api
  this.service.getData().then(d => {
     this.data = d;
     this.changeDetectorRef.detectChanges();
  });

  // observable api
  this.service.getData().pipe(takeUntil(this.unsubscribe)).subscribe((d) => {
     this.data = d;
     this.changeDetectorRef.detectChanges();
  });
}

Если ваш компонент уничтожен до выполнения обещания, вы получите attempt to use destroyed view об ошибке, когда обещание будет выполнено.

В качестве альтернативы, если вы используете наблюдаемые с takeUntil шаблоном , то, как только ваш компонент будет уничтожен, подписка будет отменена.

Это немного надуманный пример, но выполнение кода для уничтоженного компонента, вероятно, приведет к ошибкам. Если вы действительно не хотите делать это по какой-то причине: p

shusson
источник
2

Что-то, с чем я столкнулся, не было очевидно из первого прочтения учебника, и в документации была идея многоадресной рассылки.

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

Обещание заставляет вас иметь дело с одной вещью за раз, разворачивать ее данные, обрабатывать исключения, имеет языковую поддержку для таких классных вещей, как async / await, а в остальном довольно просто.

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

rpgFANATIC
источник
2

Promise:

Async Event Handler - объект Promise представляет возможное завершение (или сбой) асинхронной операции и ее результирующее значение.

Синтаксис: новый Promise (исполнитель);

Например:

var promise_eg = new Promise(function(resolve, reject) {
  setTimeout(function() {
    resolve('foo');
  }, 300);
});

promise_eg.then(function(value) {
  console.log(value);
  // expected output: "foo"
});

console.log(promise_eg);

введите описание изображения здесь

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

Наблюдаемые:

Observables - это ленивые коллекции нескольких значений с течением времени. это действительно отличный подход для асинхронных операций. это можно сделать с помощью rxjs, который поддерживает кроссплатформенность, может использовать angular / реагировать и т. д.

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

Синтаксис: import * as Rx from "@reactivex/rxjs"; для инициации:

Rx.Observable.fromEvent(button, "click"),
Rx.Subject()

так далее

подписываться: RxLogger.getInstance();

Например:

import { range } from 'rxjs';
import { map, filter } from 'rxjs/operators';

range(1, 200).pipe(
  filter(x => x % 2 === 1),
  map(x => x + x)
).subscribe(x => console.log(x));

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

Использование: это имеет больше возможностей, таких какmap, filter, pipe, map, concatMap etc

Мохидин бен Мухаммед
источник
2

Основное различие между наблюдаемым и обещаниями:

введите описание изображения здесь

Чираг
источник
2
Пожалуйста, отредактируйте свой пост и покажите фактический контент в виде текста вместо скриншотов. Другие не могут копировать и вставлять из ваших изображений. Смотрите здесь для деталей. Спасибо.
Пан
1

Наблюдаемые часто сравнивают с обещаниями. Вот некоторые ключевые отличия:

Наблюдаемые являются декларативными; расчет не начинается до подписки. Обещания выполняются немедленно при создании. Это делает наблюдаемые полезными для определения рецептов, которые можно запускать, когда вам нужен результат.

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

Наблюдаемые различают цепочку и подписку. Обещания имеют только предложения .then (). Это делает наблюдаемые полезными для создания сложных рецептов преобразования, которые будут использоваться другими частями системы, без необходимости выполнения работы.

Observables subscribe () отвечает за обработку ошибок. Обещания подталкивают к ошибкам ребенка. Это делает наблюдаемые полезными для централизованной и предсказуемой обработки ошибок.

Это самое простое отличие, которое вы можете найти в документах ANGULAR.IO. остальное ответ дается большинством правильно на своем месте

Анкита Кумари
источник
1
  1. Обещания ориентированы только на отдельные значения или решают, наблюдаемые являются потоком данных.

  2. Наблюдаемые могут быть отменены, но обещания не могут быть отменены.

Наименее известный, по крайней мере для меня

  1. Обещания всегда носят асинхронный характер, но наблюдаемые могут быть как синхронными, так и асинхронными.
Вигнеш
источник
0
  1. Обещание стремится, тогда как Наблюдаемое лениво,
  2. Обещание всегда асинхронно, в то время как Observable может быть либо синхронным, либо асинхронным,
  3. Обещание может предоставить единственное значение, тогда как Observable является
    поток значений (от 0 до нескольких значений),
  4. Вы можете применять операторы RxJS к Observable, чтобы получить новый специализированный поток.
Йогеш Вагмаре
источник
-1

Observables и Promises помогают нам работать с асинхронными функциями в JavaScript / typcript. Они очень похожи во многих случаях, однако между ними все еще есть некоторые различия.

введите описание изображения здесь

FAISAL
источник
1
Пожалуйста, отредактируйте свой пост и покажите реальный текст вместо скриншотов. Другие не могут копировать и вставлять из ваших изображений. Смотрите здесь для деталей. Спасибо.
Пан
За исключением того, что это не код, а простая информация, так что я думаю, что все в порядке, чтобы опубликовать это как изображение
Alator
1
прекратить копирование вставки из видео YouTube Kudvenkat. Даунвот от меня! :)
Пратик
-2

На эту тему уже есть много ответов, поэтому я бы не стал добавлять лишний.

Но тому, кто только начал изучать Observable / Angular и задается вопросом, какой из них использовать, сравните с Promise , я бы порекомендовал вам сохранить все Observable и преобразовать все существующие обещания в вашем проекте в Observable.

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


Хотя я ценю все отрицательные отзывы, но я все же настаиваю на своем мнении выше, если кто-то не оставит надлежащий комментарий, чтобы перечислить несколько сценариев, которые все еще могут быть полезны в вашем Angular проекте для использования Promises over Observables.

Конечно, ни одно мнение не является на 100% правильным во всех случаях, но, по крайней мере, я думаю, что 98% времени для обычных коммерческих проектов, реализованных в Angular Framework, Observable - верный путь.

Даже если вам не понравится в начале вашего простого хобби-проекта, вы скоро поймете, что почти все компоненты, с которыми вы взаимодействуете в Angular, и большинство дружественных для Angular сторонних фреймворков используют Observables, а затем вы в конечном итоге постоянно преобразовывал ваше Обещание в Observable, чтобы общаться с ними.

Эти компоненты включают, но не ограничиваются: HttpClient, построитель форм, модули / диалоги угловых материалов, хранилище / эффекты Ngrx и ngx-bootstrap.

Фактически, единственное обещание от угловой системы, с которым я имел дело в последние 2 года, - это APP_INITIALIZER.

Xinan
источник