web-dev-qa-db-ja.com

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

だから私は、オブザーバブルが今後のJavaScript MVCのいくつかでの使用に関して、約束を追い越そうとしていることを読んだことがあります。

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

更新:謝罪!虚偽の陳述を削除しました。

35
chrisjlee

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

簡単に言えば、約束はsingle値に非同期的に解決され、オブザーバブルはmultiple値を非同期的に(経時的に)。

具体例:

  • 約束:Ajax呼び出しからの応答
  • 観察可能:クリックイベント

詳細については、こちらをご覧ください。 http://reactivex.io/intro.html

オブザーバブルが約束を追い越そうとしていることを読んだことがある

ありそうもない。オブザーバブルは特定の問題に対するより良い解決策かもしれませんが、それは約束を時代遅れにするものではありません(もしそれがあなたの言うことなら)。

34
Felix Kling

約束は、1つの将来価値の表現です。オブザーバブルは、場合によっては無限の値の表現です。

Promiseは、作成後すぐにその値のフェッチをトリガーします。オブザーバブルは、サブスクライブしたときにのみ値の生成を開始します。 (それが注目に値するものでない限り、それはこの質問の範囲外です)

Promiseは、AJAX呼び出しを表すように設計されています。オブザーバブルは、イベント、データベースからのデータ、ajax呼び出しからのデータ、(おそらく無限)シーケンスなど)を表すように設計されています。

35
Moeri

Promiseは、非常に単純化されたコールバックメカニズムを提供します。Rxは、非同期プログラミングよりも強力な抽象化を提供します。 Observableはデータのストリームを表します。その後、入力データの処理方法を定義するために演算子を適用できます。

HTTPリクエストを作成してからUIコンポーネントを更新するだけであれば、Promiseを使用すれば十分です。

ただし、ほとんどのアプリは、それよりも複雑なニーズを持っている傾向があります(最初は明らかではありませんが)。 HTTPリクエストを例に取って、これをObservableとしてモデリングし、Rx演算子のいくつかを使用するとどのように役立つかを見てみましょう。

-HTTPリクエストがユーザーアクションによってトリガーされる場合、複数のHTTPリクエストを起動することに注意してください(ユーザーが検索ボックスに入力することを想像してください)。すべてのキーストロークに対してリクエストを発行したくないので、検索をThrottleして、ユーザーが300msの間入力を停止します。さらに、ユーザーがWordを入力して300ミリ秒待機し、別の文字を追加すると、後続のHTTPリクエストが実行されます。 Promisesでは、応答を受信する順序を制御できず、古いリクエストをキャンセルできないため、競合状態が発生する可能性があります。 Rxは、ストリーム間でSwitchを許可することでこれを解決し、Disposeを呼び出します古いリクエストサブスクリプションでは、もう気にしません。また、無効な検索入力を除外することもできます。たとえば、Where検索語の長さが3文字未満です。

-タイムアウト/エラー処理のサポート。 HTTPリクエストが失敗したとしましょう。Rxを使用すると、リクエストを簡単にRetryできます。

-アプリケーションの複数の部分で同じHTTP呼び出しを行う必要があるとしましょう。実際に複数回呼び出しを行うことはおそらくないでしょう。オブザーバブルを複数のコンシューマーに公開し、Replayを使用して、呼び出しが1回行われ、結果が後続のサブスクライバーにキャッシュされるようにします。 TimeSpanをReplayに提供して、期限切れのキャッシュ動作を提供することもできます。

-スケジューラーを使用したスレッド化の強力な抽象化により、並行性を制御できます。さらに良いことに、ユニットテストでテストスケジューラを使用して時間を制御し、タイムアウト、競合状態などをシミュレートできます。

これらは可能なことを示すための簡単な例です。 Rxフレームワーク内には、すべてのタイプのシナリオに対応する演算子がさらに多くあり、Rxの構成可能性により、演算子を簡単に組み合わせて必要な動作を定義できます。また、独自の再利用可能な演算子(RetryAfterDelayなど)を簡単に作成できます。

要約すると、RxはPromisesができることをはるかに超えて実行できます。今後数年間、PromisesではなくRxへの移行が続くと思います。

さらに読むには、 Angular 2ガイド のObservablesのセクションをご覧になることをお勧めします。

24
domino

Angular 2 guid で述べたように

Promiseへの変換は、多くの場合、単一のデータチャンクを取得する場合に適しています。そのため、データを受信したら完了です。

ただし、場合によっては、リクエストが1回しか実行されないことがあります。サーバーが最初の要求に応答する前に、1つの要求を開始してキャンセルし、別の要求を行うことができます。

たとえば、検索コンポーネントの場合ユーザーが検索ボックスに名前を入力すると、その検索クエリによってHTTPリクエストが繰り返されます。

Request-cancel-new-requestシーケンスは、Promiseでは実装が困難ですが、Observableでは簡単です。

コンポーネントが1つのリクエストのみでデータを取得する場合、Promiseを使用することをお勧めしますが、request-cancel-newリクエストのチェーンがある場合は、observableを使用する必要があります。

7
Parid0kht

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

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

オブザーバブルは多くの値を提供します。約束は1つを提供します。これにより、経時的に複数の値を取得するためにオブザーバブルが役立ちます。

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

Observables subscribe()はエラーの処理を担当します。 Promises子のpromiseにエラーをプッシュします。これにより、オブザーバブルは、集中化された予測可能なエラー処理に役立ちます。

公式ウェブサイトのangular=による最良の説明:

https://angular.io/guide/comparing-observables

1
asad mohd

Observables VS. Promises(by Jeremy Vilken)

新しい構文に加えて、observablesは、JavaScriptアプリケーションが非同期アクティビティを管理するための新しいパターンです。また、JavaScript言語でネイティブに実装される機能のドラフトであるため、パターンの背後に重みがあります。 RxJSは、アプリケーションでオブザーバブルを実装するために使用するライブラリです。

Promisesは、非同期呼び出しの処理を支援する別の構成要素です。これは、たとえばAPIリクエストの作成に役立ちます。プロミスには、1つのコールサイクルでのみ役立つという大きな制限があります。たとえば、ユーザークリックなどのイベントでプロミスが値を返すようにしたい場合、そのプロミスは最初のクリックで解決されます。ただし、すべてのユーザークリックアクションの処理に関心がある場合があります。通常、これにはイベントリスナを使用します。これにより、時間をかけてイベントを処理できます。これは重要な違いです。オブザーバブルは、時間の経過とともにデータを処理し続け、そのデータストリームを継続的に処理できるという点で、イベントハンドラーに似ています。

1
Masoud Bimar

Observablesを正しく理解すると、Promisesとの違いは明らかです。

複雑な概念を分かりやすく説明する最良の方法は、ゼロから実装することです。以下は、ほぼ純粋に機能するObservable実装と、Promisesでは機能しない例です。

/*** Observable type ***/

// type constructor (of a product type)

const proType = name => cons => {
  const f = (k, ...args) =>
    Object.defineProperties({["run" + name]: k}, {
      [Symbol.toStringTag]: {value: name},
      [Symbol("args")]: {value: args}
    });

  return cons(f);
};

// value constructor

const Observable = proType("Observable")
  (Observable => k => Observable(k));

/*** Observer factory ***/

const Observer = observer => {
  let isUnsubscribed = false;

  return {
    next: function(x) {
      if (isUnsubscribed)
        throw new Error("unsubscribed");

      else {
        try {
          return observer.next(x);
        }

        catch(e) {
          isUnsubscribed = true;
          this.cancel();
          throw e;
        }
      }
    },

    error: function(e) {
      if (isUnsubscribed)
        throw new Error("unsubscribed");

      else {
        try {
          return observer.error(e);
        }

        catch(e_) {
          isUnsubscribed = true;
          this.cancel();
          throw e_;
        }
      }
    },

    complete: function() {
      if (isUnsubscribed)
        throw new Error("unsubscribed");

      else {
        try {
          const r = observer.complete();
          this.cancel();
          return r;
        }

        catch(e) {
          isUnsubscribed = true;
          cancel();
          throw e;
        }
      }
    }
  };
};

/*** combinators + auxiliary functions ***/

const subscribe = observable => handlers => {
  const observer = Observer(handlers),
    cancel = observable.runObservable(observer);

  observer.cancel = cancel;
  return cancel;
};

const obsMap = f => observable =>
  Observable(observer => {
    const mapObserver = {
      next: x => observer.next(f(x)),
      error: e => observer.error(e),
      complete: () => observer.complete()
    };

    return observable.runObservable(mapObserver);
  });

/*** main ***/

// create an Observable instance

const numStream = Observable(observer => {
  let i = 0;

  const timer = setInterval(() => {
    observer.next(i++);
  }, 1000);
  
  return () => clearTimeout(timer);
});

// map a function over it

const squaredNumStream =
  obsMap(x => x * x) (numStream);

// run the observable

const cancel = subscribe(squaredNumStream) ({
  next: x => console.log(x),
  error: e => console.error(e),
  complete: () => console.log("finished")
});

// cancel it

setTimeout(cancel, 11000);

上の例では、ObservablesquaredNumStreamは、理論的に無限の値のストリームを非同期的に出力します。 Promisesを使用してこれを行うことはできません。これらは単一の将来の値を表すためです。

両方のインスタンスが互いに干渉することなく、別のsquaredNumStreamに簡単にサブスクライブできました。これは、Observablesがユニキャストであるのに対し、Promisesはマルチキャストであるためです。

squaredNumStreamは宣言時に実行されませんが、サブスクリプション後にのみ実行されます。これは、Observablesが遅延評価されるためです。一方、Promisesは熱心に評価されます。つまり、作成するとすぐに実行が開始されます。

最後に、Observablesは設計によりキャンセルできますが、Promisesはユニキャストセマンティクスがあるためキャンセルが困難です。

0
user10675354