W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
你可以經(jīng)常使用可觀察對象(Observable
)而不是承諾(Promise
)來異步傳遞值。 類似的,可觀察對象也可以取代事件處理器的位置。最后,由于可觀察對象傳遞多個值,所以你可以在任何可能構(gòu)建和操作數(shù)組的地方使用可觀察對象。
在這些情況下,可觀察對象的行為與其替代技術(shù)有一些差異,不過也提供了一些顯著的優(yōu)勢。下面是對這些差異的詳細比較。
可觀察對象經(jīng)常拿來和承諾進行對比。有一些關(guān)鍵的不同點:
.then()
語句。這讓可觀察對象可用于創(chuàng)建供系統(tǒng)的其它部分使用而不希望立即執(zhí)行的復(fù)雜菜譜。subscribe()
會負責(zé)處理錯誤。承諾會把錯誤推送給它的子承諾。這讓可觀察對象可用于進行集中式、可預(yù)測的錯誤處理。subscribe()
會執(zhí)行一次定義好的行為,并且可以再次調(diào)用它。每次訂閱都是單獨計算的。重新訂閱會導(dǎo)致重新計算這些值。Path:"src/observables.ts (observable)" 。
// declare a publishing operation
const observable = new Observable<number>(observer => {
// Subscriber fn...
});
// initiate execution
observable.subscribe(() => {
// observer handles notifications
});
then
語句(訂閱)都會共享同一次計算。Path:"src/promises.ts (promise)" 。
// initiate execution
const promise = new Promise<number>((resolve, reject) => {
// Executer fn...
});
promise.then(value => {
// handle result here
});
Path:"src/observables.ts (chain)" 。
observable.pipe(map(v => 2 * v));
.then()
語句(等價于訂閱)和中間的 .then()
語句(等價于映射)。Path:"src/promises.ts (chain)" 。
promise.then(v => 2 * v);
Path:"src/observables.ts (unsubcribe)" 。
const subscription = observable.subscribe(() => {
// observer handles notifications
});
subscription.unsubscribe();
Path:"src/observables.ts (error)" 。
observable.subscribe(() => {
throw Error('my error');
});
Path:"src/promises.ts (error)" 。
promise.then(() => {
throw Error('my error');
});
下列代碼片段揭示了同樣的操作要如何分別使用可觀察對象和承諾進行實現(xiàn)。
操作 | 可觀察對象 | 承諾 |
---|---|---|
創(chuàng)建 | new Observable((observer) => { observer.next(123); }); |
new Promise((resolve, reject) => { resolve(123); }); |
轉(zhuǎn)換 | obs.pipe(map((value) => value * 2)); |
promise.then((value) => value * 2); |
訂閱 | sub = obs.subscribe((value) => { console.log(value) }); |
promise.then((value) => { console.log(value); }) |
取消訂閱 | sub.unsubscribe(); |
承諾被解析時隱式完成。 |
可觀察對象和事件 API 中的事件處理器很像。這兩種技術(shù)都會定義通知處理器,并使用它們來處理一段時間內(nèi)傳遞的多個值。訂閱可觀察對象與添加事件處理器是等價的。一個顯著的不同是你可以配置可觀察對象,使其在把事件傳給事件處理器之前先進行轉(zhuǎn)換。
使用可觀察對象來處理錯誤和異步操作在 HTTP 請求這樣的場景下更加具有一致性。
下列代碼片段揭示了同樣的操作要如何分別使用可觀察對象和事件 API 進行實現(xiàn)。
// Setup
let clicks$ = fromEvent(buttonEl, ‘click’);
// Begin listening
let subscription = clicks$
.subscribe(e => console.log(‘Clicked’, e))
// Stop listening
subscription.unsubscribe();
function handler(e) {
console.log(‘Clicked’, e);
}
// Setup & begin listening
button.addEventListener(‘click’, handler);
// Stop listening
button.removeEventListener(‘click’, handler);
監(jiān)聽按鍵,提供一個流來表示這些輸入的值。
fromEvent(inputEl, 'keydown').pipe(
map(e => e.target.value)
);
不支持配置。
element.addEventListener(eventName, (event) => {
// Cannot change the passed Event into another
// value before it gets to the handler
});
observable.subscribe(() => {
// notification handlers here
});
element.addEventListener(eventName, (event) => {
// notification handler here
});
可觀察對象會隨時間生成值。數(shù)組是用一組靜態(tài)的值創(chuàng)建的。某種意義上,可觀察對象是異步的,而數(shù)組是同步的。 在下面的例子中,?
符號表示異步傳遞值。
obs: ?1?2?3?5?7
obsB: ?'a'?'b'?'c'
arr: [1, 2, 3, 5, 7]
arrB: ['a', 'b', 'c']
concat()
。 concat(obs, obsB)
?1?2?3?5?7?'a'?'b'?'c'
arr.concat(arrB)
[1,2,3,5,7,'a','b','c']
filter()
。 obs.pipe(filter((v) => v>3))
?5?7
arr.filter((v) => v>3)
[5, 7]
find()
。 obs.pipe(find((v) => v>3))
?5
arr.find((v) => v>3)
5
findIndex()
。 obs.pipe(findIndex((v) => v>3))
?3
arr.findIndex((v) => v>3)
3
forEach()
。 obs.pipe(tap((v) => {
console.log(v);
}))
1
2
3
5
7
arr.forEach((v) => {
console.log(v);
})
1
2
3
5
7
map()
。 obs.pipe(map((v) => -v))
?-1?-2?-3?-5?-7
arr.map((v) => -v)
[-1, -2, -3, -5, -7]
reduce()
。 obs.pipe(reduce((s,v)=> s+v, 0))
?18
arr.reduce((s,v) => s+v, 0)
18
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: