PromisesとObservablesの違いは何ですか?


1397

違いは何であるPromiseObservable角度では?

それぞれの例は、両方のケースを理解するのに役立ちます。それぞれのケースでどのようなシナリオを使用できますか?


23
この投稿を読むことをお勧めします。Angular2 promise vs observable
erolkaya84


3
このQ&Aを読むすべての人に-メンテナー、スピーカー、および長年のユーザーPoVから両方の世界に関与している誰かとして、RxJSの公式ドキュメントと約束に関するMDNドキュメントを読むことをお勧めします。私は個人的に、ここでの答えは完全に誤解を招き、不正確である私は思いますが、それらは助けようとする人々からの善意で非常に有害であると信じています。
Benjamin Gruenbaum

1
この角度の公式ドキュメントangular.io/guide/comparing-observables
fgul

そして、これがリンクが回答として受け入れられないと見なされる理由です。
Dave、

回答:


1551

約束する

AのPromiseハンドルシングルイベント非同期操作の完了または失敗しました。

注:Promiseキャンセルをサポートするライブラリは世の中にPromiseありますが、ES6 は今のところサポートしていません。

観察可能

ANはObservable似ているStream(多くの言語で)及びコールバックはイベントごとに呼び出され、ゼロ以上のイベントを通過させます。

それ以上の機能を提供するため、多くの場合よりObservableも推奨されます。ではあなたは0、1、または複数のイベントを処理する場合、それは問題ではありません。どちらの場合も同じAPIを利用できます。PromisePromiseObservable

Observableまた、キャンセル可能であるという利点Promiseがあります。サーバーへのHTTPリクエストの結果またはその他の高額な非同期操作が不要になった場合、のはサブスクリプションのキャンセルを許可しますが、通知が不要な場合でもは最終的に成功または失敗したコールバックを呼び出しますまたはそれが提供する結果。SubscriptionObservablePromise

観測可能では提供事業者のようなmapforEachreduce配列に類似し、...

強力なような事業者もありretry()、またはreplay()多くの場合、非常に便利です...。


180
それで、単一のコールバックのケースでObservableの代わりにPromiseを使用する十分な理由がありますか、それともObservableもそのように機能できるため、そこで使用する必要がありますか?基本的に、「すべてを観察可能」にすることは良い習慣ですか、それともPromiseはまだその場所にありますか?
Josh Werts 2016

75
リアクティブスタイルを使用する場合は、どこでもオブザーバブルを使用してください。オブザーバブルがある場合は、簡単に作成できます。それらを混ぜると、もうそれほどきれいではありません。リアクティブスタイルを気にしない場合は、イベントのストリームのキャンセル可能および監視可能を気にしない単一のイベントにpromiseを使用できます。
ギュンターZöchbauer

35
@GünterZöchbauerねえ-Observablesや関数型プログラミングに対する議論はありません。私が単にNG2で主にhttpを介してObservablesに実行している人々が、Promisesを介してObservablesを使用して呼び出しを行う本当の理由はないと信じていると単に述べています。彼らは約束を使うことによって実用的なものを失うことはありません。デバウンス演算子と再​​試行演算子は関係ありません。ng-debounceを使用してデバウンスでき、呼び出しが失敗すると予想される場合は、通常、コードに問題があります。呼び出しの再試行を処理する必要があったのは、HVTの不安定なサードパーティAPIをクエリしているときだけでした。
VSO 2017年

92
ただしPromiseasync/ とともにawaitコードを再びフラットにすることを忘れないでください!ほとんどの状況で、そしてロケット科学を扱っていないプロジェクトでは、不必要に複雑なメソッドのチェーンを使用して、これらの恐ろしい入れ子関数を記述する必要はありません。async/をawait今日のようなトランスパイラーで使用しTypeScriptrxjsボイラープレートなしで実際の人間が読めるフラットコードを書くことができます。rxjsそれは本当に提供することがたくさんあるので、あなたはおそらくまだ選択された状況で時々まだ必要になるでしょう。
evilkos 2017

15
この答えは誤解を招くものであり、オブザーバブルはストリームのようなものではなく、ストリームを返す関数のようなものです
Benjamin Gruenbaum 2017

335

どちらPromisesObservables助け、私たちが対処することを抽象化を提供してくれる非同期当社のアプリケーションの性質。それらの違いは@Günterと@Reluによって明確に指摘されました。

コードスニペットは1000語に相当するので、以下の例を理解して理解しやすくしてください。

素晴らしいものを@Christoph Burgdorfに感謝 記事


Angularは、HTTPを扱うための約束の代わりにRx.js Observablesを使用します。

あなたが構築していると仮定します 入力中に結果を即座に表示検索機能を。おなじみのようですが、その作業には多くの課題があります。

  • ユーザーがキーを押すたびにサーバーエンドポイントをヒットするのは望ましくありません。 HTTPリクエストでます。基本的に、ユーザーがキーストロークごとではなく、ユーザーが入力を停止したときにのみヒットさせたいと考えています。
  • で検索エンドポイントをヒットしないでください 後続のリクエスト同じクエリパラメータで。
  • 順不同の応答に対処します。処理中の複数のリクエストが同時にある場合、予期しない順序で返されるケースを考慮する必要があります。最初にcomputerと入力して、停止するとリクエストが送信され、carと入力して停止すると、リクエストが送信されると想像してください。これで、2つのリクエストが処理中です。残念ながら、コンピューターの結果を含むリクエストは、の結果を含むリクエストの後に返されます。

デモは単純に2つのファイルで構成されます:app.tswikipedia-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]);
  }
}

特定の検索用語を使用して、Wikipedia APIに対してリクエストJsonpを行うサービスを注入しています。我々は呼んでいることに注意してくださいから得るためにします。最終的には、検索メソッドの戻り値の型としてa になります。GETtoPromiseObservable<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し、検索メソッドを介してその機能をテンプレートに公開します。テンプレートは単にキーアップにバインドして呼び出しますsearch(term.value)

WikipediaServiceのsearchメソッドが返すというPromiseの結果を展開し、それを単純な文字列の配列としてテンプレートに公開して、*ngForループしてリストを作成できるようにします。

上の約束ベースの実装の例を参照してください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 fromの@angular/formし、コンポーネントの名前termの下のフィールドとして公開します。

舞台裏で、termは自動的にサブスクライブ可能なObservable<string>asプロパティvalueChangesを公開します。今、私たちは持っていることをObservable<string>、ユーザの入力を克服して呼び出すように簡単ですdebounceTime(400)私たちにObservable。これはObservable<string>、400msの間新しい値が来ていない場合にのみ新しい値を放出するnewを返します。

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

AngularでHttpを使用している限り、通常の使用例ではObservable over Promiseを使用しても大きな違いはないことに同意します。ここで実際に関連する利点はありません。私は将来的にいくつかの高度なユースケースを見ることができることを願っています:)


もっと詳しく知る


31
私はHttpサービスをObservableベースに変えるという決定を完全には買いません。私が聞くすべての説明は同じ例に依存しています:用語による検索。しかし、それはブラウザイベントの処理に関するものです。非同期のhttpリクエストを処理するときにそれを適用することの利点は何ですか?
Alex Pollan 2017

1
混合パターンを回避するための決定は偶然でしたか?
Alex Pollan 2017

6
@AlexPollan、実際には、http://www.delex.net/ja-jabber/…でこのLesとのポッドキャストでオブザーバブルを返すhttpサービスの利点についての良い説明があります。最終的に、主な利点は、上記のリンクで説明されているオブザーバブルとその使用例をキャンセルできることです-少し工夫されていますが、複数のAPIを呼び出し、最初の応答のみを気にすると、呼び出したAPIのうち最初に戻ってきたら、他のAPIへのリクエストをキャンセルできます。
nikolasleblanc 2017年

2
@nikolasleblanc、そのために$ q.race()を使用できると確信していますか?
jameslouiz 2017年

2
@AlexPollan、利点は、ObservableベースのHTTPサービスにより、飛行中のHTTPリクエストを簡単にキャンセルできることです。trungk18の回答の競合状態は、後続のリクエストを行う前に、HTTPオブザーバブルから登録解除するだけで解決できます。RXJS switchMapは、別のオブザーバブル(valueChangesなど)によってトリガーされるHTTPリクエストに使用できます。スタンドアロンHTTPオブザーバブルの場合、手動でサブスクライブを解除して再サブスクライブできます。
Stevethemacguy

236

PromisesObservablesはどちらも、JavaScriptの非同期機能の操作に役立ちます。それらは多くの場合非常に似ていますが、2つの間にもいくつかの違いがあり、promiseはhttp呼び出しのasynchronousような方法で解決される値です。一方、オブザーバブルは一連の非同期イベントを処理します。それらの主な違いは次のとおりです。

約束する:

  • 1つのパイプラインがある
  • 通常は非同期データリターンでのみ使用します
  • キャンセルするのは簡単ではありません

観測可能:

  • キャンセル可能
  • 再試行や再試行時など、本質的に再試行可能です
  • 複数のパイプラインでデータをストリーミングする
  • マップ、フィルターなどの配列のような操作
  • イベントなどの他のソースから作成できます
  • これらは関数であり、後でサブスクライブできます

また、違いを視覚的に示すために、以下のグラフィックイメージを作成しました。

約束と観測可能な画像


4
「簡単にキャンセルできない」と約束して、キャンセルすることはできますか?
Pardeep Jain 2017

10
はい、それらをキャンセルする方法もあります...ブルーバードまたはサードパーティのライブラリを使用する人もいます... AngularのQライブラリを使用してキャンセルする方法もいくつかあります...しかし、あまり便利ではない
Alireza

パイプラインが1つあると、利点がある場合があります。APP_INITIALIZERで、複数のパイプラインがある場合、それがときどき終了することも、複数回終了することもありません。
windmaomao

6
をキャンセルすることPromiseは、どのように約束するかについて考えるのに間違った方法です。Promise唯一の非同期互換性のある方法でハンドル成功または失敗への責任、それ..あなたは、httpリクエストをキャンセルしたい場合は、リクエストではなく、約束をキャンセルし、いずれかの約束を履行または拒絶キャンセルの結果を確認します。jsfiddle.net/greggman/ea0yhd4p
gman

2
@gmanその通りです。約束は単にいくつかの将来の価値を表しています値を生成する操作を表すものではありませ。値をキャンセルすることはできません。値を再試行することはできません。それは単なる価値です。これは、またはあってもなくてもよい存在はまだ、それがかもしれない例外が発生したため、存在しないが、それはそれです。
ヨナアップルツリー2018

75

約束

  1. 定義:関数を非同期で実行し、その戻り値(または例外)を使用できるようにしますが、実行時に一度だけです。
  2. 怠惰ではない
  3. キャンセルできません(キャンセルをサポートするPromiseライブラリは世の中にありますが、ES6 Promiseはこれまでのところサポートしていません)。2つの可能な決定は
    • 拒否する
    • 解決する
  4. 再試行できません(Promiseは、再試行機能を持つという約束を返した元の関数にアクセスできる必要がありますが、これは悪い習慣です)

観測可能

  1. 定義:関数を非同期で実行し、実行時にそれらの戻り値を連続シーケンスで(複数回)使用するのに役立ちます。
  2. 時間の経過時に値を出力するため、デフォルトではLazyです。
  3. コーディング作業を簡素化する多くの演算子があります。
  4. ある条件に基づいてオブザーバブルを再試行する必要がある場合も、必要に応じて1つのオペレーターの再試行を使用して再試行できます。retryWhenを使用できます。

    :インタラクティブな図とともにオペレーターのリストは、RxMarbles.comから入手できます


67

Observablesの1つの欠点が回答にありません。プロミスはES7の非同期/待機機能の使用を許可します。それらを使用すると、同期関数呼び出しのように非同期コードを記述できるため、コールバックは不要になります。Observableがこれを行う唯一の可能性は、それらをPromiseに変換することです。ただし、それらをPromiseに変換すると、戻り値は1つだけに戻ります。

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

参考資料Rx Observableで「待機」するにはどうすればよいですか?


21
また、誰もこのPromiseのキラーな特典を指摘しなかった理由にも驚かされました-async / awaitによるシンプルさと透明性。フラットなコードを書くためだけにPromiseに切り替えました。単純なビジネスロジックとUI対話コードは、ロケットサイエンスのように見えてはならず、リアクティブな拡張機能のネストされた地獄によって汚染されるべきではありません。また、async / awaitは将来だけでなく、トランスパイラーを使用しているパブリックプロダクションアプリでも使用できます。TypeScript 2.3を使用していますが、実際の言語のように素晴らしいです。
evilkos 2017

いいですが、リアクティブな方法で考えて、すべてRxOperatorsで考えると、これはキラー機能ではないかもしれません
JorgeTovar

37

PromiseとObservableはどちらも非同期呼び出しのみを処理します。

これらの違いは次のとおりです。

観察可能

  1. 一定期間に複数の値を出力します
  2. Observableをサブスクライブするまで呼び出されません
  3. unsubscribe()メソッドを使用してキャンセルできます
  4. map、forEach、filter、reduce、retry、retryWhen演算子を提供します

約束する

  1. 一度に1つの値のみを発行します

  2. .thenおよび.catchなしでサービスを呼び出します

  3. キャンセルできません

  4. オペレーターを提供していません


2
promiseは正確にはどういう意味ですか?観測可能なものは複数の値を放出しますが、オブザーバブルは複数の値を放出します
Abel

2
約束はまったく価値を生み出しません-約束時間の経過に伴う価値です。Promiseはその値を複数のサブスクライバーにマルチキャストします。いったんPromiseを保持すると、すでに値があります。オブザーバブルは関数のようなもので、サブスクライブするとアクションが呼び出されます。
Benjamin Gruenbaum

1
@BenjaminGruenbaumそれでも複数のサブスクライバーの平均を取得できませんでした。リンクまたは例を提供してください。ありがとう
ディーパックパティダー

2
observable1.subscribe(subscriber1)、observable1.subscribe(subscriber2)- 関数を複数回呼び出します。
Benjamin Gruenbaum

2
投稿を編集して、スクリーンショットではなく実際のテキストを表示してください。他の人はあなたの画像からコピーして貼り付けることができず、多くの文法エラーを修正することもできません。詳細はこちらをご覧ください。ありがとうございました。
パン

26

この答えは遅いですが、私は以下の違いを要約しました、

観察可能:

  1. 観察可能なだけされfunctionとるan observerと返します function Observer: an object with next, error.
  2. 観察者に可能にするsubscribe/unsubscribe、そのデータストリームに、観察者に次の値を発し、notify約オブザーバerrors約観察者に知らせますstream completion
  3. オブザーバーはfunction to handle next value、エラーとストリームの終わり(UIイベント、http応答、Webソケットのデータ)を提供します。
  4. multiple values時間とともに機能する
  5. それはcancel-able/retry-able、そのよう支援事業者をmap,filter,reduceなど
  6. Observableの作成は、次のようになりObservable.create()ます--onメソッドを呼び出すことができるObservableを返しますObserver Observable.from()--配列または反復可能オブジェクトをにObservable Observable.fromEvent()変換します-- イベントをObservableにObservable.fromPromise()変換します--PromiseをObservableに変換しObservable.range()ます--指定された範囲の整数のシーケンスを返します

約束

  1. promiseは、将来終了するタスクを表します。

  2. 約束になるresolved by a value;

  3. 約束は例外によって拒否されます。

  4. ないcancellable、そしてそれは戻るa single value

  5. 約束は機能を公開する (then)

    -その後、新しいを返します promise

    -の許可は、attachmentに基づいて実行され stateます。

    - handlersある guaranteed中で実行しますorder attached


20

私はPromiseが最善の解決策である問題を扱ったばかりであり、役に立つ場合にこの質問に出くわした人のためにここでそれを共有します(これはまさに私が以前に探していた答えでした):

Angular2プロジェクトには、いくつかのパラメーターを取り、フォームのドロップダウンメニューに値を入力するための値リストを返すサービスがあります。フォームコンポーネントが初期化されるとき、同じパラメーターを複数回使用して同じサービスを複数の異なるドロップダウンメニューを定義するために呼び出す必要がありますが、サービスを呼び出すためにすべての変数を単にキューに入れると、最後の1つだけが成功し、残りのエラーが発生しますアウト。データベースからフェッチするサービスは、一度に1つの要求しか処理できませんでした。

すべてのドロップダウンメニュー変数を正常に設定する唯一の方法は、最後のリクエストが完了するまで新しいリクエストが処理されないようにサービスを呼び出すことでした。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;
          })  }

コンポーネントで関数を定義してから、ngOnInitでinitializeDropDowns()を呼び出しました。

fetchValueList関数はPromiseを返すため、最初の呼び出しは最初のlistCodeを渡し、Promiseが解決されると、戻り値は.thenブロックのデータ変数にあり、this.firstValList変数に割り当てることができます。関数がデータを返したので、サービスが終了し、2番目のlistCodeで再度呼び出しても安全であることがわかります。戻り値は次の.thenブロックのdata変数にあり、this.secondValList変数に割り当てます。

これを必要なだけチェーンして、すべての変数を設定できます。最後のコードブロックでは、returnステートメントを省略してブロックを終了します。

これは、コンポーネントの初期化時に複数回呼び出す必要のある単一のサービスがあり、サービスを再度呼び出す前にフェッチを完了して値を返す必要がある非常に特殊なユースケースですが、この場合は、 Promise / .thenメソッドが理想的でした。


3
これは確かに(高次)オブザーバブルでも可能です。たとえばscan()、順次オブザーバブルのストリームを構築するために使用できます。ただし、アプローチはより明確で理解しやすいかもしれません。
lex82

1
「then」を「switchMap」に置き換えて、オブザーバブルでまったく同じことを行うことができます。
C.ヒラリアス博士2017

1
私が理解しているように、switchMapの問題は、すべてのリクエストを並行して開始し、すべてのリクエストが返されるまで待機してから、呼び出し元の関数に値を返すことですが、私の状況では、1つのサーバーではできません並行して複数回呼び出します(新しい要求が入ってくると、サーバーは未完了の要求をドロップするため)。新しい呼び出しを開始する前に、データベースサービスへの各呼び出しが完了していることを確認する必要がありました。おそらくそれを解決する唯一の方法です。
スティーブンR.スミス

1
チェーンされたmergeMapを使用しなかったのはなぜですか?私があなたのコードを理解している限り、これはかなり単純で、あなたの例と同じくらいうまく機能します。@ StephenR.Smith
Ore

1
@Ore別の回答と同じ問題を解決するコード例を追加できますか?良い参考になるでしょうし、将来的にはリファクタリングの良い機会になるかもしれません。要件は、コードがバックエンドサービスを並行して呼び出すことができない場合は、それを呼び出し、戻り値を待って再度呼び出す必要があることです。
Stephen R. Smith

20

私は他のすべての答えがあなたの疑問を解決するはずだと思います。それにもかかわらず、私はオブザーバブルが関数型プログラミングに基づいていることを追加したかっただけであり、map、flatmap、reduce、zipなどのそれに付属する関数が非常に便利であることがわかりました。特にAPIリクエストに依存しているときにWebが達成する一貫性は、残忍な改善です。

このドキュメントは、reactiveXの公式ドキュメントであり、最も明確であると思うので、強くお勧めします

オブザーバブルに興味がある場合は、この3部構成の投稿をお勧めします。http//blog.danlew.net/2014/09/15/grokking-rxjava-part-1/

これはRxJava向けですが、概念は同じであり、非常によく説明されています。reactXのドキュメントでは、各関数に同等のものがあります。RxJSを探す必要があります。


18

約束する:

  • 単一の将来価値を提供します。
  • 怠惰ではありません。
  • キャンセルできません。

観察可能:

  • 時間の経過とともに複数の値を放出します。
  • 怠惰;
  • キャンセル可能;
  • マップ、フィルター、リデュース、および類似の演算子をサポート

必要に応じて、AngularでHTTPを呼び出すときにオブザーバブルの代わりにプロミスを使用できます。


16

概要:

  • PromisesとObservablesの両方は、非同期操作の処理に役立ちます。これらの非同期操作が完了すると、特定のコールバックを呼び出すことができます。
  • Promiseは1つのイベントしか処理できません。Observableは、時間の経過に伴うイベントのストリーム用です
  • 保留中のプロミスはキャンセルできません
  • Observableが出力するデータは、演算子を使用して変換できます

オブザーバブルはpromiseが提供するすべての機能(+追加)を備えているため、非同期動作を処理するために常にオブザーバブルを使用できます。ただし、Observablesが提供するこの追加機能が不要な場合もあります。次に、ライブラリをインポートして使用するためのオーバーヘッドが余分になります。

Promiseを使用する場合:

結果を処理したい非同期操作が1つある場合は、promise を使用します 。例えば:

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

したがって、promiseは、解決または拒否するコードを実行します。resolveまたはrejectのいずれかが呼び出されると、promiseは保留状態から解決または拒否状態に移行します。promise状態が解決されると、then()メソッドが呼び出されます。promise状態が拒否されると、catch()メソッドが呼び出されます。

Observablesを使用する場合:

処理が必要な(データの)ストリームが長期にわたって存在する場合は、Observablesを使用します。ストリームは、時間の経過とともに利用可能になる一連のデータ要素です。ストリームの例は次のとおりです。

  1. クリックなどのユーザーイベント、またはキーアップイベント。ユーザーは時間の経過とともにイベント(データ)を生成します。
  2. WebSocketは、クライアントがサーバーにWebSocket接続を確立した後、時間の経過とともにデータをプッシュします。

Observable自体は、次のイベントが発生したとき、エラーが発生したとき、またはObservableが完了したときに指定されます。次に、このオブザーバブルをサブスクライブしてアクティブにし、このサブスクリプションで3つのコールバックを渡すことができます(常にすべてを渡す必要はありません)。成功時に実行される1つのコールバック、エラーに対して1つのコールバック、完了時に1つのコールバック。例えば:

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

オブザーバブルを作成する場合、オブザーバーを引数として提供するコールバック関数が必要です。この観測では、あなたがして呼び出すことができますonNextonCompletedonError。次に、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. 現在、観測可能な例。ここでも、非同期タスクを処理するオブザーバーであるオブザーバーに関数を渡します。promiseのresolveとは異なり、次のメソッドがあり、その代わりにサブスクライブします。

  2. したがって、どちらも非同期タスクを処理します。それでは違いを見てみましょう。


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

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

約束と観察可能な違い

約束する

  1. 1つの値を解決または拒否し、一度に1つの値の非同期タスクを処理できます。
  2. promiseは、完了した非同期値を解決すると、使用できなくなります。1回限りの使用で、ここでは不十分です。
  3. キャンセル不可
  4. オペレーターのrxjsサポートはありません。

観察可能

  1. 複数の非同期値を出力する機能。
  2. イベントまたは値のストリームを処理するために使用されます。多数のタスクまたは値の配列があり、値が挿入されるたびに自動的に処理されるようにしたいとします。この配列に値をプッシュすると、そのすべてのサブスクライバーが最新の値を自動的に受け取ります。
  3. Observableは、入力の変更、繰り返される間隔、すべての子コンポーネントへの値のブロードキャスト、Webソケットプッシュ通知などを監視するのに役立ちます。
  4. unsubscribeメソッドを使用していつでもキャンセルできます。
  5. 約束の最後のもう1つの良い点は、rxjsオペレーターのサポートです。多くのパイプオペレーターには、主にマップ、フィルター、switchMap、combinateLatestなどがあり、サブスクライブする前に監視可能なデータを変換します。

ここに画像の説明を入力してください



6

PromisesとObservablesの両方は、非同期操作の処理に役立ちます。これらの非同期操作が完了すると、特定のコールバックを呼び出すことができます。

AngularはHTTPを処理するための約束の代わりにRxJSからのObservablesを使用します

Below are some important differences in promises & Observables.

プロミスとオブザーバブルの違い


1
表のデータは正しくないようです。タイトルを入れ替える必要があります
Derrick.X

1
投稿を編集して、実際のコンテンツをスクリーンショットではなくテキストとして表示してください。他の人はあなたの画像からコピーして貼り付けることができません。詳細はこちらをご覧ください。ありがとうございました。
パン

6

非同期アクティビティが終了または失敗すると、Promiseは単一のイベントを発行します。

Observableは(多くの言語の)ストリームのようなもので、すべてのイベントにコールバックが必要な場合に、少なくとも0個以上のイベントを渡すことができます。

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はLazyです。「観測可能」は遅いです。サブスクライブするまで呼び出されません。
  • Observableは、unsubscribe()メソッドを使用してキャンセルできます
  • 追加のObservableは、map、foreach、filter、reduce、retry、retryWhenなどの多くの強力な演算子を提供します。

Angular PromiseとObservables


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

以下は、promiseとObservableのいくつかの重要な違いです。

約束する

  • 単一の値のみを発行します
  • キャンセル不可
  • 共有できない
  • 常に非同期

観察可能

  • 複数の値を発します
  • 呼び出されたとき、または誰かがサブスクライブしているときにのみ実行されます
  • キャンセル可能
  • 複数のサブスクライバーが共有し、その共有値をサブスクライブできます。そして、すべてのサブスクライバーが単一の時点で実行されます。
  • おそらく非同期

よりよく理解するには、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

簡潔な答え :

Observableの優れています。Promiseのすべての機能に加えて、追加機能があります。


長い答え:

約束:

  • 1回限りの使用「データを1回返す」
  • キャンセルしない
  • 1人のリスナー
  • ソケットは1つのリスナーをサポートしません

観察可能:

  • データが変化するたびに何度もデータを返す
  • サポートキャンセル
  • サポートソケット
  • 多くのリスナーをサポートし、データが変更されたときに通知する
  • サポートマップ、フィルター、削減

オブザーバブルは客観的に優れているとは言えません。ここのさまざまな回答に注目されているObservablesにはいくつかの欠点があります。私にとって際立っているのは、Observableの複雑さであり、await / asyncと直接連動しないことです。Observableを使用するときの動作を判断できないため、個人的には操作が非常に難しいと思います。それを生成したコードを調べる必要があります。一方、Promiseを使用すると、常にその機能を正確に把握できます。たとえば、Observableにサブスクライブすると、副作用(httpリクエストなど)が発生する場合とそうでない場合があります。
ヨナアップルツリー2018

角度の場合、それはあなたのケースに依存します。ほとんどの場合、さまざまな場所、ソケット、キャンセル、マップ、フィルター、削減に影響を与えるサービスといくつかのデータを使用します。約束はそれらをサポートしないので、それはそれらのケースでより良いでしょう。再びそれはあなたのケースに依存します
Amr Ibrahim

2

受け入れられた答えは一般的には良いですが、Angular Componentsを扱う場合、キャンセルをサポートしているため、ほとんどの場合に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();
  });
}

promiseが解決される前にコンポーネントが破棄されると、promiseが解決されるattempt to use destroyed viewときにエラーが発生します。

または、takeUntilパターンでオブザーバブルを使用する場合、コンポーネントが破棄されるとすぐにサブスクリプションがキャンセルされます。

これは少し不自然な例ですが、破壊されたコンポーネントのコードを実行すると、バグが発生する可能性があります。何らかの理由で実際にそれをしたくないのであれば:p


2

私がそれに遭遇した何かは、チュートリアルとドキュメントの最初の読みからは明らかではありませんでしたが、マルチキャストのアイデアでした。

デフォルトでは、複数のサブスクリプションがObservableで複数の実行をトリガーすることに注意してください。単一のHTTP呼び出しObservableへの複数のサブスクリプションは、.share()(マルチキャストを有効にする)場合を除き、複数の同一のHTTP呼び出しをトリガーします。

promiseは、一度に1つの事柄に対処し、そのデータをアンラップし、例外を処理し、async / awaitなどのすばらしいものを言語でサポートし、それ以外の場合は非常に重要です。

Observableにはたくさんの魅力がありますが、使用しているパワーを理解する必要があります。理解していないと誤用される可能性があります。


2

約束する:

非同期イベントハンドラー-Promiseオブジェクトは、非同期操作の最終的な完了(または失敗)とその結果の値を表します。

構文: new Promise(executor);

例えば:

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について: 1つのパイプラインがあるため、呼び出されたときに1回だけ値を返します。その一方向ハンドラなので、一度呼び出されるとキャンセルできない場合があります。when()then()で使用できる便利な構文

観察可能なもの:

オブザーバブルは、時間の経過に伴う複数の値のレイジーコレクションです。それは非同期操作のための本当に素晴らしいアプローチです。これは、クロスプラットフォームのサポートを備えたrxjsで行うことができ、angular / reactなどで使用できます。

そのストリームライナーのような行動。マルチパイプラインにすることができます。したがって、一度定義すると、サブスクライブして多くの場所で結果を返すことができます。

構文: 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

オブザーバブルはしばしば約束と比較されます。主な違いは次のとおりです。

オブザーバブルは宣言型です。計算はサブスクリプションまで開始されません。プロミスは作成と同時に実行されます。これにより、オブザーバブルは、結果が必要なときにいつでも実行できるレシピを定義するのに役立ちます。

Observableは多くの値を提供します。約束はそれを提供します。これにより、observableは時間の経過とともに複数の値を取得するのに役立ちます。

Observableはチェーンとサブスクリプションを区別します。Promiseには.then()句しかありません。これにより、オブザーバブルは、作業を実行させることなく、システムの他の部分で使用される複雑な変換レシピを作成するのに役立ちます。

Observables subscribe()はエラー処理を担当します。約束は子どもの約束に誤りを押しやります。これにより、observableは集中型で予測可能なエラー処理に役立ちます。

これは、ANGULAR.IOのドキュメントで最も単純な違いです。残りの答えはほとんどの人が自分の場所で正しいと答えています


1
  1. 約束は単一の値または解決にのみ焦点が当てられており、オブザーバブルはデータのストリームです。

  2. オブザーバブルはキャンセルできますが、約束はキャンセルできません。

最も知られていないものは、少なくとも私にとっては

  1. 約束は常に非同期の性質のものですが、オブザーバブルは同期と非同期の両方にすることができます。

0
  1. 約束は熱心ですが、オブザーバブルは怠惰ですが、
  2. Promiseは常に非同期ですが、Observableは同期でも非同期でもかまいません。
  3. Promiseは単一の値を提供できますが、Observableは
    値のストリーム(0から複数の値)です。
  4. RxJSオペレーターをObservableに適用して、新たに調整されたストリームを取得できます。

-1

ObservablesとPromiseは、JavaScript / typescriptの非同期機能を操作するのに役立ちます。それらは多くの場合非常に似ていますが、それらの間にはまだいくつかの違いがあります。

ここに画像の説明を入力してください


1
投稿を編集して、スクリーンショットではなく実際のテキストを表示してください。他の人はあなたの画像からコピーして貼り付けることができません。詳細はこちらをご覧ください。ありがとうございました。
パン

コードではなくプレーンな情報を除いて、画像として投稿してもいいと思います
Alator

1
KudvenkatのYouTubeビデオからのコピー貼り付けを停止します。私から反対投票!:)
Pratik

-2

このトピックにはすでにたくさんの回答があるので、冗長なものは追加しません。

しかし、Observable / Angularの学習を始めたばかりで、どれをPromiseと比較するのか疑問に思っている人には、すべてをObservableに保ち、プロジェクト内のすべての既存のPromiseを Observableに変換することをお勧めします。

単にAngularフレームワーク自体とそのコミュニティがすべてObservableを使用しているからです。したがって、フレームワークサービスまたはサードパーティのモジュールを統合し、すべてをチェーン化することは有益です。


私はすべての反対投票に感謝しますが、AngularプロジェクトでPromises over Observablesを使用するのに役立つ可能性があるいくつかのシナリオをリストするために誰かが適切なコメントをしない限り、私は上記の意見を主張します。

もちろん、すべてのケースで100%正しいという意見はありませんが、少なくともAngularフレームワークで実装された通常の商用プロジェクトの98%の時間では、Observableが正しい方法だと思います。

単純な趣味のプロジェクトの開始点で気に入らなくても、Angularで操作するほぼすべてのコンポーネントにすぐに気付き、AngularフレンドリーなサードパーティフレームワークのほとんどがObservablesを使用しているため、彼らと通信するために、あなたの約束を観察可能なものに常に変換することになりました。

これらのコンポーネントには、HttpClient、フォームビルダー、Angularマテリアルモジュール/ダイアログ、Ngrxストア/エフェクト、ngx-bootstrapが含まれますが、これらに限定されません。

実際、私が過去2年間に扱ったAngularエコシステムからの唯一の約束はAPP_INITIALIZERです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.