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

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

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

45 ответов

Решение

обещание

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

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

наблюдаемый

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

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

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

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

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

И то и другое 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 Википедии с заданным поисковым термином. Обратите внимание, что мы называем 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 мы можем воспользоваться преимуществами Angular. formControl директивы. Чтобы использовать эту директиву, нам сначала нужно импортировать 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"/>

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

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


Учить больше

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

обещание:

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

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

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

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

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

Обещания:

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

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

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

В ответах отсутствует один недостаток 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?

обещания

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

Наблюдаемые

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

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

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

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

Допустим, вы хотите пойти на пляж. Вы должны принять решение, основываясь на погоде. У вас есть 3 способа:

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

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

3- На этот раз вы включаете радио и слушаете погодный канал, который транслирует погодные условия 24/7. В этом сценарии вместо получения одного единственного ответа ответ продолжается. Этот ответ похож на subscription для observable. наблюдаемая - это «погода», а подписка - «радиосигналы, которые держат вас в курсе». Пока ваше радио включено, вы получаете все доступные обновления. Вы не пропустите никакой информации, пока не выключите радио. Когда выключаешь радио, значит "ты отписался".

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

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

  1. Наблюдаемый это просто function это занимает an observer и возвращает 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 и т.п.
  6. Создание Observable может быть - 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 являются guaranteed выполнить в order attached;

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

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

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

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

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

Я только что имел дело с проблемой, где 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 был идеальным.

Обзор:

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

Вы всегда можете использовать наблюдаемое для работы с асинхронным поведением, так как наблюдаемое обладает всеми функциями, которые предлагает обещание (+ дополнительно). Однако иногда эта дополнительная функциональность, которую предлагают 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. Пользовательские события, например, нажатия или события keyup. Пользователь генерирует события (данные) с течением времени.
  2. Веб-сокеты: после того, как клиент подключится к серверу через веб-сокет, он с течением времени передает данные.

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

Promise:

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

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

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

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

Сначала обещание vs наблюдаемое сходство

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

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

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

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

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


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

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

Я парень с фотографиями, этого не хватало в других ответах:

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

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

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


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

Обещания:

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

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

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

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

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

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

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

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

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

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

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

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

Напротив, Observables позволяют вам разрешать (или, как мы говорим, "излучать") несколько значений. Вот как это будет выглядеть:

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

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

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

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

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

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

Обещание:

  • Обещание не лениво
  • Обещание нельзя отменить

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

  • Наблюдаемый - ленивый. "Наблюдаемое" работает медленно. Он не вызывается, пока мы на него не подпишемся.
  • Observable можно отменить с помощью метода unsubscribe()
  • Кроме того, Observable предоставляет множество мощных операторов, таких как map,foreach, filter, reduce, retry, retryWhen и т. Д.

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

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

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

Below are some important differences in promises & Observables.

  1. Promise нетерпелив, тогда как Observable ленив,
  2. Promise всегда асинхронен, а Observable может быть синхронным или асинхронным,
  3. Promise может предоставлять одно значение, тогда как Observable - это
    поток значений (от 0 до нескольких значений),
  4. вы можете применить операторы RxJS к Observable, чтобы получить новый адаптированный поток.

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);

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

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

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

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

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

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

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

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

обещание

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

наблюдаемый

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

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

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

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

      myPromise.then((resolvedValue) => {
    console.log(resolvedValue);
}, (error) => {
    console.log(error);
});

Наблюдаемый: это объект, предоставляемый библиотекой Rxjs, который помогает нам работать с реактивным программированием в js-приложениях, который обеспечивает цепочку и подписку для обработки сложных приложений, имеющих преимущество отмены, предоставляя множество значений одновременно, кроме того, мы может извлечь выгоду из применения цепочки других операторов, таких как retry() , map(), filter() , switchMap()и т. д., что помогает справиться со сложными вариантами использования и тяжелыми пользовательскими интерфейсами.

Пример мгновенного поиска:

      search(terms: Observable<string>) {
    return terms.pipe(
      debounceTime(400),
      distinctUntilChanged(),
      switchMap((term) => this.searchEntries(term))
    );
  }

Пример нескольких параллельных вызовов APIS:

      let character = this.http.get('https://jsonplaceholder.typicode.com/todos');
    let characterHomeworld = this.http.get(
      'https://jsonplaceholder.typicode.com/posts'
    );

    forkJoin([character, characterHomeworld]).subscribe((results) => {
      console.log('result °', results[0]);
      console.log('result 1', results[1]);
    });

Я вижу, что многие люди используют аргумент, что 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

Вкратце, основные различия между Promise и Observable заключаются в следующем:

  • Promise нетерпелив, тогда как Observable ленив,
  • Promise всегда асинхронен, а Observable может быть синхронным или асинхронным,
  • Promise может предоставить одно значение, тогда как Observable - это поток значений (от 0 до нескольких значений),
  • вы можете применить операторы RxJS к Observable, чтобы получить новый адаптированный поток.

более подробно можно найти в этой статье

Еще одно отличие: Global vs Imported

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

Наблюдаемые, реактивные расширения для JavaScript требуют и импортаустановкиRxJS перед использованием

      import { Observable } from 'rxjs';
Другие вопросы по тегам