可觀察對象用法實戰
-
輸入提示(type-ahead)建議
-
可觀察對象可以簡化輸入提示建議的實現方式。典型的輸入提示要完成一系列獨立的任務:
-
從輸入中監聽數據。
-
移除輸入值前後的空白字符,並確認它達到了最小長度。
-
防抖(這樣才能防止連續按鍵時每次按鍵都發起 API 請求,而應該等到按鍵出現停頓時才發起)
-
如果輸入值沒有變化,則不要發起請求(比如按某個字符,然後快速按退格)。
-
如果已發出的 AJAX 請求的結果會因爲後續的修改而變得無效,那就取消它。
-
完全用 JavaScript 的傳統寫法實現這個功能可能需要大量的工作。使用可觀察對象,你可以使用這樣一個 RxJS 操作符的簡單序列:
import { fromEvent } from 'rxjs';
import { ajax } from 'rxjs/ajax';
import { debounceTime, distinctUntilChanged, filter, map, switchMap } from 'rxjs/operators';
const searchBox = document.getElementById('search-input-box');
const typeahead = fromEvent(searchBox, 'input').pipe(
map((e: KeyboardEvent) => (e.target as HTMLInputElement).value),
filter(text => text.length > 2),
debounceTime(10),
distinctUntilChanged(),
switchMap(() => ajax('/api/test'))
);
typeahead.subscribe(data => {
// Handle the data from the API
});
指數化退避
- 指數化退避是一種失敗後重試 API 的技巧,它會在每次連續的失敗之後讓重試時間逐漸變長,超過最大重試次數之後就會徹底放棄。 如果使用承諾和其它跟蹤 AJAX 調用的方法會非常複雜,而使用可觀察對象,這非常簡單:
import { pipe, range, timer, zip } from 'rxjs';
import { ajax } from 'rxjs/ajax';
import { retryWhen, map, mergeMap } from 'rxjs/operators';
function backoff(maxTries, ms) {
return pipe(
retryWhen(attempts => zip(range(1, maxTries), attempts)
.pipe(
map(([i]) => i * i),
mergeMap(i => timer(i * ms))
)
)
);
}
ajax('/api/test')
.pipe(backoff(3, 250))
.subscribe(data => handleData(data));
function handleData(data) {
// ...
}