プロミスとオブザーバーブルの違いは何ですか?

angular promise rxjs angular-promise angular-observable


Angularで PromiseObservable の違いは何ですか?

それぞれのケースについての例があれば、両方のケースを理解する上で参考になると思います。どのようなシナリオで、それぞれのケースを使うことができるのでしょうか?




Answer 1 Günter Zöchbauer


Promise

A Promise 扱う単一のイベントをするとき非同期操作の完了または失敗しました。

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

Observable

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

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

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

Observableは、配列に似た mapforEachreduce などの演算子を提供します

retry()replay() などの強力な演算子もあり、非常に便利です。




Answer 2 trungk18


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

コードスニペットは千の言葉の価値があるので、それらを簡単に理解するために、以下の例を通ってみましょう。

素晴らしい記事をありがとう@Christoph Burgdorf


AngularではHTTPを扱うためにプロミスの代わりにRx.jsのObservablesを使用しています。

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

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

デモは単純に app.tswikipedia-service.ts の2つのファイルで構成されます。ただし、実際のシナリオでは、おそらくさらに分割します。


以下は、説明されているエッジケースを処理しない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 するに対する要求WikipediaのAPIを与えられた検索語と。 Observable<Response> から Promise<Response> に取得するために toPromise を呼び出すことに注意してください。最終的には、 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のsearchメソッドが返すそれを単純な文字列の配列としてテンプレートに *ngFor ます。これにより、* 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"/>

このコンポーネントでは、 @angular/form から FormControl のインスタンスを作成し、コンポーネントの名前項目の下のフィールドとして公開します。

舞台裏で、termObservable<string> 、サブスクライブできるプロパティ valueChanges として自動的に公開します。今、私たちは持っていることを Observable<string> 、ユーザの入力を克服して呼び出すのと同じくらい簡単です debounceTime(400) 私たちの Observable 。これは新しいを返します Observable<string> 、400ミリ秒間新しい値が来ていない場合にのみ新しい値を出力 Observable <string>が返されます。

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)

PlunkerでのObservable実装の例を参照してください

順不同の応答については、記事全文を確認してください http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html

私がAngularでHttpを使っている限り、通常のユースケースではPromiseよりもObservableを使ってもあまり違いがないことに同意します。実際にはどのような利点もあまり関係ありません。将来的にはもっと高度なユースケースが見られることを期待しています。)


詳細はこちら




Answer 3 Alireza


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

promise:

  • 一本道
  • 通常は非同期データリターンでのみ使用します
  • 取り消せない

observable:

  • はキャンセル可能
  • は、retry や retryWhen のような性質上、再試行が可能です。
  • マルチパイプラインでのストリームデータ
  • マップ、フィルタなどのような配列的な操作が可能
  • は、イベントなどの他のソースから作成することができます。
  • は後にサブスクライブされる可能性のある関数です。

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

Promises and Observables image




Answer 4 Aravind


Promises

  1. 定義:関数を非同期で実行し、その戻り値(または例外)を一度だけ使用するのに役立ちます、実行時にです。
  2. 怠け者ではない
  3. キャンセルできない(キャンセルに対応しているプロミスのライブラリはあるが、ES6のプロミスは今のところない)という2つの判断が考えられます。
    • Reject
    • Resolve
  4. 再試行できません(Promiseは、再試行機能を持つという約束を返した元の関数にアクセスする必要がありますが、これは悪い習慣です)

Observables

  1. 定義:関数を非同期で実行し、その戻り値を実行時に連続した順序で(複数回)使用するのに役立ちます。
  2. デフォルトでは、時間が進むと値を出すので、Lazyになっています。
  3. コーディングの手間を簡略化してくれるオペレーターが多い。
  4. ある条件に基づいてオブザーバブルを再試行する必要がある場合も、必要に応じて1つのオペレーターの再試行を使用して再試行できます。retryWhenを使用できます。

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




Answer 5 besserwisser


答えに欠けているObservablesの欠点が1つあります。プロミスはES7のasync/await関数を使用することができます。これを使えば、同期関数を呼び出すように非同期コードを書くことができるので、コールバックはもう必要ありません。唯一の可能性はObservablesをPromiseに変換することです。しかし、ObservablesをPromiseに変換すると、戻り値は1つだけになります。

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

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