Promise vs Observable

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

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

18 ответов


обещание

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

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

наблюдаемых

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

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

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

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

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


обещает:

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

параметры:

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

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

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

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


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


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

обещаем:

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

заметно:

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

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

Promises and Observables image


обещания

  1. определение: позволяет запускать функции асинхронно и использовать их возвращаемые значения (или исключения), но только один раз при выполнении.
  2. Не Лень
  3. не подлежит отмене. Два возможных решения
    • отклонение
    • Resolve
  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

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


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

Observable:

  1. Observable-это просто 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 etc.
  6. создание наблюдаемого может быть -Observable.create() - возвращает Observable, который может вызывать методы на -Observer Observable.from() - преобразует массив или iterable в -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, таких как повтор и повтор. С другой стороны, обещания требуют от вызывающего абонента доступа к исходной функции, которая вернула обещание, чтобы иметь возможность повторной попытки.

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

   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

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


обещаем:

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

Observable:

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

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


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

Observable-обеспечьте множественное будущее значение. Ленивый. Возможность отмены . Он предоставляет другие методы live map, filter, reduce.


описание:

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

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

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

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

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 обратного вызова (не всегда должны проходить все). Один обратный вызов будет выполнен для succes, один обратный вызов для ошибки и один обратный вызов для завершения. Например:

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-запрос) наблюдаемые могут непрерывно испускать изменения состояния на основе наблюдателей, которые подписываются на них.

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

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


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

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


ответ:

обещает:

  • один раз используйте "вернуть данные один раз"
  • нет отмена
  • слушатель
  • Отсутствие Поддержки Одного Гнезда Слушатель!--25-->

заметно:

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

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

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

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


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

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

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

эти компоненты включают, но не ограничиваются: HttpClient, Конструктор форм, модули углового материала / диалоги, ngrx store / effects и NGX-bootstrap.

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


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

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