Observable は EventEmitters とは異なります。RxJSサブジェクトを使用してマルチキャストされる場合など、場合によっては EventEmitters のように動作することがありますが、通常は EventEmitters のようには動作しません。
つまり、RxJS Subjectは EventEmitter に似ていますが、RxJS Observableはより一般的なインターフェースです。オブザーバブルは、引数がゼロの関数に似ています。
次の点を考慮してください。
function foo() {
console.log('Hello');
return 42;
}
var x = foo.call(); // same as foo()
console.log(x);
var y = foo.call(); // same as foo()
console.log(y);
もちろん、出力として次のように表示されることを期待しています。
"Hello"
42
"Hello"
42
上記と同じ動作を記述できますが、Observables を使用します。
var foo = Rx.Observable.create(function (observer) {
console.log('Hello');
observer.next(42);
});
foo.subscribe(function (x) {
console.log(x);
});
foo.subscribe(function (y) {
console.log(y);
});
出力は同じです。
"Hello"
42
"Hello"
42
これは、関数と Observables の両方が遅延計算であるためです。関数を呼び出さないと、これconsole.log('Hello')
は起こりません。また、Observable では、「呼び出し」( subscribe
)を行わないと、このようなconsole.log('Hello')
ことは起こりません。さらに、「呼び出し」または「サブスクライブ」は独立した操作です。2 つの関数呼び出しが 2 つの別個の副作用をトリガーし、2 つの Observable サブスクライブが 2 つの別個の副作用をトリガーします。副作用を共有し、サブスクライバーの存在に関係なく熱心に実行する EventEmitters とは対照的に、Observable は実行を共有せず、怠惰です。
これまでのところ、関数と Observable の動作に違いはありません。この StackOverflow の質問は、「RxJS Observables vs functions?」という表現の方が適切でしょう。
Observable は非同期であると主張する人もいます。そうではありません。関数呼び出しをログで囲むと、次のようになります。
console.log('before');
console.log(foo.call());
console.log('after');
明らかに出力が表示されます。
"before"
"Hello"
42
"after"
そして、これは Observables と同じ動作です:
console.log('before');
foo.subscribe(function (x) {
console.log(x);
});
console.log('after');
そして出力:
"before"
"Hello"
42
"after"
foo
これは、関数のように、 のサブスクリプションが完全に同期的であることを証明しています。
では、Observable と関数の実際の違いは何でしょうか?
オブザーバブルは時間の経過とともに複数の値を「返す」ことができますが、機能することはできません。あなたはこれを行うことはできません:
function foo() {
console.log('Hello');
return 42;
return 100; // dead code. will never happen
}
関数は 1 つの値のみを返すことができます。ただし、オブザーバブルはこれを行うことができます。
var foo = Rx.Observable.create(function (observer) {
console.log('Hello');
observer.next(42);
observer.next(100); // "return" another value
observer.next(200);
});
console.log('before');
foo.subscribe(function (x) {
console.log(x);
});
console.log('after');
同期出力の場合:
"before"
"Hello"
42
100
200
"after"
しかし、値を非同期的に「返す」こともできます:
var foo = Rx.Observable.create(function (observer) {
console.log('Hello');
observer.next(42);
observer.next(100);
observer.next(200);
setTimeout(function () {
observer.next(300);
}, 1000);
});
出力あり:
"before"
"Hello"
42
100
200
"after"
300
結論として、
func.call()
「すぐに(同期的に)1つの値を与える」ことを意味します
obsv.subscribe()
「値を教えてください。多分それらの多くは、おそらく同期的に、おそらく非同期的に」
これが、Observables が関数 (引数を持たない) の一般化である方法です。