Обещание против наблюдаемого


может кто-нибудь объяснить разницу между Promise и Observable в угловой?

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

18 860

18 ответов:

обещание

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

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

наблюдаемых

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

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

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

Observable обеспечивает операторы как map,forEach,reduce, ... похоже на массив

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

обещает:

  • возвращает одно значение
  • не расторгнут
  • более читаемый код с try / catch и async / await

параметры:

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

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

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

спасибо @Christoph Burgdorf за удивительный статьи


угловой использует Rx.JS Observables вместо обещаний для работы с HTTP.

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

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

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


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

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 запрос от Wikipedia API с заданным поисковым термином. Обратите внимание, что мы называем 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 цикл через него и построить список для нас.

см. Пример Обещание на основе реализация на Plunker


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

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

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

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

обещаем:

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

заметно:

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

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

Promises and Observables image

обещания

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

параметры

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

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

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

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

читайте далее: как я могу "ждать" на Rx Наблюдаем?

 Promises vs Observables

обещания и наблюдаемые оба обрабатывают только асинхронный вызов.найти выше изображение для главной разницы.

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

Observable:

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

обещание:

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

  2. обещает стать resolved by a value;

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

  4. не cancellable и это возвращает a single value

  5. обещание выставить функцию (then)

    -затем возвращает новый promise;

    разрешает attachment из этого будет выполняться на основе на state;

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

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

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

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

  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 возвращает обещание, поэтому первый вызов передает Первый listCode, и когда обещание разрешается, возвращаемое значение находится в переменной данных.затем блок, где мы можем назначить его на это.переменная firstValList. Поскольку функция вернула данные, мы знаем, что служба закончилась, и безопасно снова позвонить со вторым listCode, возвращаемое значение находится в переменной данных в следующем .затем блокируем и присваиваем его этому.переменная secondValList.

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

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

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

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

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

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

Я надеюсь, что это помогает, просто попытался внести свой вклад здесь. :)

параметры vs обещания

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

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

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

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

numberPromise.then(value => console.log(value));
// will simply print 5

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

    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

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

обещаем:

  • обеспечить одно будущее значение;
  • не ленивый;
  • не подлежит отмене;

заметно:

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

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

Promise-обеспечить одно будущее значение. Не лениться. Не отменить-возможность. Он либо отвергнет, либо разрешит.

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

описание:

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

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

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

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

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() метод называется.

когда использовать наблюдаемые:

используйте наблюдаемые, когда есть поток с течением времени, который вам нужно обрабатывать. В самом наблюдаемом указывается, когда произошло следующее событие, когда произошла ошибка или когда наблюдаемое завершено. Затем мы можем подписаться на этот observable, который активирует его, и в этой подписке мы можем передать 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. Затем, когда наблюдаемое подписано на него, вызовет соответствующие обратные вызовы, переданные в подписку.

наблюдаемые и обещания оба обеспечивают средства для работы с асинхронные действия в JavaScript. Пока обещает либо отклонить/разрешить на основе завершения одного асинхронного события (http-запрос) наблюдаемые могут непрерывно выдавать изменения состояния на основе наблюдателей, которые подписываются на них.

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

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

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

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


ответ:

обещает:

  • один раз использовать "возврат данных один раз"
  • нет отмена
  • слушатель
  • Нет Поддержки Сокета Один Слушатель

Observable:

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

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

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

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


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

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

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

эти компоненты включают, но не ограничиваются: HttpClient, Строитель форма, угловой материал модулей/диалоги, Ngrx магазин/эффекты и фабриката необходмо предусмотреть-загрузочный.

фактически, единственное обещание от Angular eco-system, с которым я имел дело в последние 2 года, - это APP_INITIALIZER.

объясните в ссылке на угловые Http-вызовы для удаленного Api: Promises используется для поддержания состояния асинхронных вызовов. один данные получены из удаленного Api и показать в поле зрения

и наблюдаемых исходите из наблюдаемого шаблона и вводите Rxjs, когда он дает вам объект для обновления данных несколько раз по всему потоку в качестве наблюдаемых данных.