Observables 不像 EventEmitters。在某些情况下,它们可能像 EventEmitter 一样,即当它们使用 RxJS Subjects 进行多播时,但通常它们不像 EventEmitters。
简而言之,一个 RxJS Subject就像一个 EventEmitter,但是一个 RxJS Observable是一个更通用的接口。Observables 更类似于零参数的函数。
考虑以下:
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
这是因为函数和 Observable 都是惰性计算。如果您不调用该函数,console.log('Hello')
则不会发生。同样对于 Observables,如果您不“调用”( subscribe
),console.log('Hello')
则不会发生。另外,“调用”或“订阅”是一个独立的操作:两个函数调用触发两个单独的副作用,两个 Observable 订阅触发两个单独的副作用。与 EventEmitter 共享副作用并且无论订阅者是否存在都急切执行相反,Observables 没有共享执行并且是惰性的。
到目前为止,函数的行为和 Observable 之间没有区别。这个 StackOverflow 问题可以更好地表述为“RxJS Observables vs functions?”。
有些人声称 Observables 是异步的。那不是真的。如果您使用日志包围函数调用,如下所示:
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 和函数之间的真正区别是什么?
Observables 可以随着时间的推移“返回”多个值,而函数不能。你不能这样做:
function foo() {
console.log('Hello');
return 42;
return 100; // dead code. will never happen
}
函数只能返回一个值。然而,Observables 可以这样做:
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()
意思是“立即(同步)给我一个值”
obsv.subscribe()
意思是“给我价值。也许很多,也许是同步的,也许是异步的”
这就是 Observables 是函数的泛化(没有参数)。