可觀察量是一種能惰性推送的集合,他能夠包含多個值。下面的表格對比了推送和拉取2種方式:react
單值 | 多值 | |
---|---|---|
拉取 | Function | Iterator |
推送 | Promise | Observable |
舉例來講,下列Observable 在被訂閱以後會當即推送(同步)值1,2,3
,而值4
將會在1秒以後被推送到訂閱者,以後這個流進入完成狀態:app
var obserable = Rx.Observable.create(function(observer){ //注意參數的命名 observer.next(1); observer.next(2); observer.next(3); setTimeout(function(){ observer.next(4); observer.complete(); },1000); });
爲了調用以上的Observable並輸出其中的值,須要訂閱這個流:異步
console.log('just before subscribe'); observable.subscribe({ next:x => console.log('got value:',x), error:err => console.log('something wrong occurred: ' + err), complete:() => console.log('done') }); console.log('just after subscribe');
執行以後會輸出:async
just before subscribe got value 1 got value 2 got value 3 just after subscribe got value 4 done
拉取和推送是數據生產者和數據使用者之間進行數據交換的2種形式。函數
在拉取系統中,數據使用者決定什麼時候從數據生產者那裏接收數據。數據生產者自身並不知道數據什麼時候會被傳遞給使用者。lua
每個js函數都是一個拉取系統。函數是一個數據生產者,經過在別處被調用,他返回的單一值將會被投入計算。日誌
ES2015又引入了新的拉取系統,generator和迭代器(function*
)。調用iterator.next()
來消費從迭代器(數據生產者)中拉取到的數據。code
Producer | Consumer | |
---|---|---|
Pull | 被動的:被請求的時候返回數據 | 主動的:決定數據什麼時候被請求 |
Push | 主動的:按照本身的步驟返回數據 | 被動的:接收的數據後做出反應 |
在推送系統中,數據生產者決定什麼時候把數據推送給使用者,使用者本身並不知道什麼時候可以接收到數據。server
Promise是當今js中最多見的一種推送系統。和函數不一樣,Promise(數據生產者)精確的控制時機,將數據「推送」給業已註冊的回調函數(數據使用者)。
RxJS引入了Observables,一個新的JS推送系統。
一個Observable是一個包含多個值的「數據生產者」,它會將數據推送給Observer(數據使用者)。
A Function is a lazily evaluated computation that synchronously returns a single value on invocation.
A generator is a lazily evaluated computation that synchronously returns zero to (potentially) infinite values on iteration.
A Promise is a computation that may (or may not) eventually return a single value.
An Observable is a lazily evaluated computation that can synchronously or asynchronously return zero to (potentially) infinite values from the time it's invoked onwards.
Function
是一種惰性計算方式,當他被調用時會同步的返回一個值。
generator
是一種惰性計算方式,會在迭代中同步的返回0到無限個(可能的話)返回值。
Promise
使用一種處理方法,最終可能會(或可能不會)返回一個值。
Observable
是一種惰性處理方法,當被調用的時候,能夠同步也能夠異步的返回0到無限個(可能的話)返回值。
有別於流行的說法,Observable既不像多個EventEmitter
,也不像一種能返回多個值的Promise
。
在一些場合,好比廣播消息時,Observer看起來很像EventEmitter
,在RxJS中,被稱爲Subject
。而在大多數狀況下,Observable並不像EventEmitter
。
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); });
上面2種狀況實際上是因爲函數和Observable都是一種惰性的計算。若是你不調用函數,那麼console.log('Hello')
就不會被執行,也不會有輸出。一樣的,只用當「調用」(經過subscribe
訂閱)Observable,纔會有輸出。
此外,調用和訂閱都是孤立運行的。2個函數分別被調用會產生2個效果,2個Observable訂閱者會產生2個獨立的效果。
不像EventEmitter
會派發它的狀態而且不管是否有訂閱者都會執行那樣,Observable不會派發狀態並且是惰性的。
訂閱observable,相似於調用一個函數
有些聲音宣稱Observable是異步的,這是不對的。若是你使用一個函數來輸出日誌,像這樣:
console.log('before'); console.log(foo.call()); console.log('after');
輸出是:
"before" "Hello" 42 "after"
一樣的行爲,使用Observable:
console.log('before'); foo.subscribe(function(x){ console.log('Hello'); return x; }); console.log('after');
輸出是同樣的:
"before" "Hello" 42 "after"
以上證實了訂閱foo
以後,效果和函數同樣,都是同步的。
不管是同步方式仍是異步方式,obsverable均可以擇其一來傳遞返回值。
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); 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); }); console.log('before'); foo.subscribe(function(x){ console.log(x); }); console.log('after');
輸出爲:
"before" "Hello" 42 100 200 "after" 300
結論:
func.call()
意味着「同步的返回一個值」。
observable.subscribe()
意思是「返回任意數量的值,同步式、異步式二擇其一。」