web-dev-qa-db-ja.com

Observables(Rx.js)はES2015ジェネレーターとどのように比較されますか?

私が理解している限り、非同期プログラミングワークフローを解決するためのテクニックは次のとおりです。

  1. コールバック(CSP)
  2. 約束

新しいアプローチ:

  1. Rx.js Observables(またはmostjs、bacon.js、xstreamなど)
  2. ES6ジェネレーター
  3. 非同期/待機

現在、コールバックと約束からこれらの新しいアプローチに移行しています。私が現在理解しているのは、Async/Awaitは、ES2015ジェネレーターの上にあるよりクリーンな抽象化のようなものです。

私が理解できないのは、ObservablesとGeneratorsの概念的な違いです。私は両方を広範囲に使用しており、問題なく使用しています。

私を混乱させているのは、ObservablesとGeneratorsのユースケースです。結局、彼らは同じ問題、つまり非同期性に取り組んでいるという結論に達しました。私が見る潜在的な違いは、ジェネレーターが本質的にコードに命令セマンティクスを提供するのに対し、Rxjsを使用するObservablesはリアクティブパラダイムを提供するように見えることだけです。しかし、それはそれですか?

それがObservableとGeneratorのどちらかを選択するための基準である必要がありますか?長所と短所は何ですか。

全体像が欠けていますか?

また、Observableが最終的に将来のEcmascriptになると、Promise(キャンセル可能トークン付き)/ Observable/Generatorsは互いに競合しますか?

25
Harshal Patil

オブザーバブルプッシュの変更、したがって、それに反応する関数ではなく、オブザーバブルが制御されます。一方、ジェネレーターでは、ジェネレーターから値を引き出す必要があります。したがって、新しい値に反応する関数は、新しい値の準備ができたときに決定します。

オブザーバブルを使用した背圧に問題がありましたが、ジェネレーターを使用すると、必要なだけゆっくりと値を出力できます。

編集:最後の質問。約束は一度だけ放出される観測量であるため、互いに競合することはないと思います。本当の戦いはasync/await vs observablesであり、async/awaitは有利なスタートを切っており、すでにC#(そして現在はNode.js)にあると思います。しかし、オブザーバブルはその甘いFRPの感触を持っており、関数型プログラミングは非常にクールなので、どちらもマインドシェアのかなりの部分になると思います。

Edit2:Cycle.jsとxstreamの作成者であり、Rx.jsの寄稿者であるAndréStaltzが、ジェネレーターとObservablesの関係に関するgreat記事を書きました(2018-01-31) 。特に、彼は両方が共通の基本クラスからどのように継承するかを示しています。

そして今、消費者はリスナー(「オブザーバー」)またはプーラーになることができます。プロデューサーをプルするかどうかは消費者次第です。また、プロデューサーはリッスン可能(「監視可能」)またはプル可能(「反復可能」)のどちらでもかまいません。データをプロアクティブに送信するか、オンデマンドでのみ送信するかはプロデューサー次第です。ご覧のとおり、コンシューマーとプロデューサーはどちらも同じタイプの単純な関数です。

(num、ペイロード)=> void

したがって、私たちが構築する演算子は、リアクティブプログラミングとイテラブルプログラミングの両方で機能します。これら2つのモード間の境界線がぼやけており、オブザーバブルとイテラブルの関係ではなく、プロデューサーとコンシューマーの間のデータの変換だけであるためです。

私はそれを読むことをお勧めします[ リンク ]。この記事では、リアクティブで反復可能なプログラミングに使用されるコールバックの仕様である「 Callbags "」を紹介しています。彼はその仕様を実装して、反復可能プログラミングとリアクティブプログラミングの両方で 小さなライブラリ を作成します。記事を読んでライブラリをチェックするように誘うために、彼が紹介した仕様に基づいた7kbライブラリの例をいくつか示します。

リアクティブプログラミングの例

毎秒刻む時計から最初の5つの奇数を選び、それらの観察を開始します。

const {forEach, interval, map, filter, take, pipe} = require('callbag-basics');

pipe(
  interval(1000),
  map(x => x + 1),
  filter(x => x % 2),
  take(5),
  forEach(x => console.log(x))
);

// 1
// 3
// 5
// 7
// 9

反復可能なプログラミング例

数字の範囲から、それらの5つを選び、4で割ってから、それらを1つずつ引き出し始めます。

const {forEach, fromIter, take, map, pipe} = require('callbag-basics');

function* range(from, to) {
  let i = from;
  while (i <= to) {
    yield i;
    i++;
  }
}

pipe(
  fromIter(range(40, 99)), // 40, 41, 42, 43, 44, 45, 46, ...
  take(5), // 40, 41, 42, 43, 44
  map(x => x / 4), // 10, 10.25, 10.5, 10.75, 11
  forEach(x => console.log(x))
);

// 10
// 10.25
// 10.5
// 10.75
// 11
17
Sam H.

Rxjsオブザーバブルは、非同期ジェネレーター、つまりプロミスを生成するジェネレーターと見なすことができます。 .nextを呼び出したときにコンテンツの準備ができているとは限らないという理由だけで(通常のジェネレーターとは対照的に)

  • サブスクライバーは、ジェネレーターのコンテンツを無限ループに永続的に消費します(.nextを呼び出します)
  • 返された約束が解決される(または取り消される)のを待って、必要なことを実行します
  • オブザーバブル(非同期ジェネレーターで作成)は、ジェネレーターのリターンで完了します。

続きを読む

非同期イテレータの提案

4
Flavien Volken