今天通過《奇舞周刊》中的一篇《構(gòu)建流式應(yīng)用—RxJS詳解》對RxJS做了一個簡單的了解谋竖。
RxJS是Reactive Extensions for javascript的簡寫,我的理解是Javascript的靈活擴展揣钦。
文章借助RxJS優(yōu)化了使用普通方式實現(xiàn)的搜索功能。簡述一下該搜索功能粱哼,用戶輸入查詢內(nèi)容,后臺返回查詢結(jié)果狐粱。功能非常簡單,我們一般實現(xiàn)是獲取該搜索框胆数,兼聽搜索框的輸入事件肌蜻,將搜索框內(nèi)容發(fā)送到后臺,后臺根據(jù)搜索內(nèi)容返回數(shù)據(jù)必尼,前端拿到數(shù)據(jù)后展現(xiàn)到頁面蒋搜。
先來用普通方式實現(xiàn)一下這個搜索功能。
var input = document.querySelector("#text");
input.addEventListener("keyup",(e)=>{
var searchText = e.target.value;
$.ajax({
url: `search.com/${searchText}`,
success:data=>{
render(data);
}
})
});
這里有兩點需要優(yōu)化:
- 多余的請求判莉。用戶的每次輸入都會做出響應(yīng)齿诞,比如用戶想搜索『手指餅』,結(jié)果【手】骂租,【指】兩個字都會觸發(fā)輸入事件。
- 已無用的請求仍再執(zhí)行斑司。用戶輸入【可樂】搜索結(jié)果沒有返回時渗饮,又輸入了【手指餅】,這時【可樂】的搜索結(jié)果返回了宿刮,這顯然是不正確的互站。
對于多余請求的情況可以使用定時器setTimeout的方式來處理。如下:
var input = document.querySelector("#test"),
timer = null;
input.addEventListener('keyup',(e){
clearTimeout(timer);
timer = setTimeout(()=>{
var searchText = e.target.value;
$.ajax({
url: `search.com/${searchText}`,
success:data=>{
render(data);
}
})
},250)
})
對于無用請求的處理僵缺,可以提前聲明一個當前搜索的狀態(tài)變量胡桃,并把這個狀態(tài)變量與數(shù)據(jù)一起返回,判斷該變量與當前輸入是不是相同磕潮,如果相同則把數(shù)據(jù)渲染到頁面翠胰。如下:
var input = document.querySelector("#test"),
timer = null,
currentSearch = "";
input.addEventListener('keyup',(e){
clearTimeout(timer);
timer = setTimeout(()=>{
currentSearch = "書";
var searchText = e.target.value;
$.ajax({
url: `search.com/${searchText}`,
success:data=>{
if(data.search == currentSearch){
render(data);
}else{
......
}
}
})
},250)
})
這樣使用普通方式來實現(xiàn)搜索功能就完成了。下面我們看一下使用RxJS如何來實現(xiàn)該功能自脯。
首先實現(xiàn)個簡陋版的:
var input = document.querySelector("#test");
Rx.Observable.fromEvent(input,"keyup")
.pluck('target','value')
.flatMap(url=>Http.get(url))
.subscribe(data=>render(data))
在這里fromEvent之景、pluck、flatMap是RxJS提供的一系列操作膏潮,RxJS提供的操作非常豐富锻狗,想了解更多可以查詢RxJS文檔。這里的調(diào)用方式采用的鏈式調(diào)用焕参,使用過JQuery的話對鏈式調(diào)用是非常熟悉了轻纪。下面說明一下每句的作用:
Rx.Observable.fromEvent(input,"keyup") // fromEvent用于兼聽事件,事件觸發(fā)時叠纷,將事件event轉(zhuǎn)成可流動的Observable進行傳輸刻帚。
.pluck("target","value") // 將輸入的event,輸出成event.target .value
.flatMap(url=>Http.get(url)) // 將請求搜索結(jié)果輸出回給Observer
.subscribe(data=>render(data)) // Observer針對返回的數(shù)據(jù)進行渲染
接下來看一下RxJS針對多余請求的優(yōu)化
var input = document.querySelector("#test");
Rx.Observable.fromEvent(input,"keyup")
.debounce(250) // 經(jīng)過250毫秒后,沒有流入新值讲岁,才將值轉(zhuǎn)入下一個環(huán)節(jié)
.pluck('target','value')
.flatMap(url=>Http.get(url))
.subscribe(data=>render(data))
RxJS針對無用請求的處理特別方便我擂,直接使用flatMapLatest替換flatMap:
var input = document.querySelector("#test");
Rx.Observable.fromEvent(input,"keyup")
.debounce(250)
.pluck('target','value')
.flatMapLatest(url=>Http.get(url)) // 取消上一個已無用的請求衬以,只保留最后的請求結(jié)果流
.subscribe(data=>render(data))
這樣使用RxJS來實現(xiàn)搜索功能就完成了。對比兩種實現(xiàn)使用Rx從代碼量上有明顯的優(yōu)勢校摩。
文章簡單介紹了Rx的實現(xiàn)原理看峻,個人覺得Rx更像是鋼鐵廠,原材料(各類數(shù)據(jù)或事件)經(jīng)過高溫(Rx.Observable)轉(zhuǎn)成鋼水(流)衙吩,再經(jīng)過模具(Rx.Observer)得到想要的不同形式的鋼材(渲染)互妓。 RxJS以Asynchronous Data streams為核心,RxJS可以將事件坤塞,變量冯勉,屬性等等轉(zhuǎn)換成data streams,通過觀察這些data streams摹芙,并依據(jù)其創(chuàng)建的side effets進行對應(yīng)的操作灼狰。這只是個簡單的入門,《使用 RxJS 構(gòu)造復(fù)雜單頁應(yīng)用的數(shù)據(jù)邏輯》這篇文章針對RxJS的高級使用做了介紹浮禾,有興趣可以讀一下交胚。