什么是Rxjs
RxJS是使用Observables 的響應(yīng)式編程的庫,它使編寫異步或基于回調(diào)的代碼更容易。隨著深入你會發(fā)現(xiàn)它采用了訂閱者模式,其中也帶有純函數(shù)的思想,比如Rxjs5中我們把“副作用”都寫在.do()中。直到在使用了RxJS 6之后才了解其少有人意識到的另一面——流。
什么是流?node中的stream,gulp中的管道流... 這里我們不用專業(yè)術(shù)語來解釋,用生活中大家熟悉的的例子來類比,比如“河流”。
河流有什么特點?至少有兩個特點:水往低處流,河流雖然可能會蜿蜒盤旋,但是朝向固定,比如我國的長江和黃河就都是由西向東流。在RxJS中數(shù)據(jù)的流向也是固定的,就是從發(fā)送者到訂閱者?;径既缦旅孢@種形式:
河道有無數(shù)的分支也有無數(shù)的合并,在Rxjs中的是,通過不同的操作符將數(shù)據(jù)流拆分處理聚合又拆分。RxJS 6 相對于 RxJS 5(這里指5.5以下的版本,因為pipe函數(shù)在RxJS 5.5中作為新特性已被引入) 來說不僅修改了一部分操作符的名稱,同時做了一個較大的改動,引入了管道(pipe)。
這種寫法上的變化就帶來了用法上的變化,以前的固定“河流”可以通過“管道”(pipe)來控制形成靈活的“水流”。
Rxjs vs Promise
Rxjs 和傳統(tǒng)的Promise在處理異步問題上有什么差距呢?再代碼層面什么是Rxjs說到底是要理解什么是Observable。RXJS是Observable的Javascript實現(xiàn)。
promise相較于Rxjs而言功能更單一 promise 只能將一個數(shù)據(jù)的狀態(tài)由pending轉(zhuǎn)換成resoloved或者rejected.而Rxjs可以處理多個數(shù)據(jù)對應(yīng)complete和error狀態(tài)但是Rxjs同時又擁有next方法。Observable是惰性的,需要subscribe的時候才輸出值。promise內(nèi)部狀態(tài)是不可控制的,執(zhí)行了就無法終止。而Observable可以定義如何取消異步方法。這也就是我下面會討論到的一個異步場景。
輸入框中輸入字符,按回車發(fā)送一個請求,并將返回的結(jié)果變成一個todo item。如果在請求返回結(jié)果前又一次按下回車或add按鈕,如果相同則不進(jìn)行任何操作,如果不同則取消掉上次的請求并發(fā)送新的請求。(實際的場景往往是發(fā)送個http請求該請求會返回的很慢,業(yè)務(wù)上加上心跳檢查,如果前一次在心跳間隔內(nèi)無返回則再次調(diào)用請求,同時需要拋棄前一次請求的返回,并且此時有可能調(diào)用參數(shù)不一樣的該接口從而造成數(shù)據(jù)不一致的問題)對于Promise實現(xiàn)我們不只要維護(hù)一個定時器timer 同時還要維護(hù)一個全局變量。
而Rxjs 我們可以通過switchMap 切換 Observable達(dá)到該效果
為什么使用 switchMap?
switchMap和其他打平操作符的主要區(qū)別是它具有取消效果。在每次發(fā)出時,會取消前一個內(nèi)部 observable (你所提供函數(shù)的結(jié)果) 的訂閱,然后訂閱一個新的observable 。你可以通過短語切換成一個新的 observable來記憶它。
它能在像 typeaheads 這樣的場景下完美使用,當(dāng)有新的輸入時便不再關(guān)心之前請求的響應(yīng)結(jié)果。在內(nèi)部observable長期存活可能會導(dǎo)致內(nèi)存泄露的情況下,這也是一種安全的選擇,例如,如果你使用mergeMap和interval,并忘記正確處理內(nèi)部訂閱。記住,switchMap 同一時間只維護(hù)一個內(nèi)部訂閱,在示例1中可以清楚出看到這一點。
不過要小心,在每個請求都需要完成的情況下,考慮寫數(shù)據(jù)庫,你可能要避免使用 switchMap。如果源observable發(fā)出速度足夠快的話,switchMap可以取消請求。在這些場景中,mergeMap是正確的選擇。
這里的switchMap其實是map and switch,而switch操作符的行為是:
如果Observable中流動的數(shù)據(jù)也是Observable,switch會將數(shù)據(jù)流中最新的一個 Observable訂閱并將它的值傳遞給下一個操作符,然后取消訂閱之前的 Observable。
簡直就是為心跳檢查量身定做。不管你異步的狀態(tài)是怎么樣switchMap中的Observable只訂閱最新的一個。下面有個例子可以幫你很清晰的理解:
嘗試一些場景中使用Rxjs
1.寫一個基于 websocket 的在線聊天室,每次websocket收到新消息,不可能都立刻渲染出來,如果是用于生產(chǎn),同時會有很多人說話wx渲染很大程度會有性能問題。用JS寫的話,你需要維護(hù)一個數(shù)組,和一個timer,收到消息,先放進(jìn)數(shù)組,然后timer負(fù)責(zé)把消息渲染出來,同時還要考慮清理timer,類似:
而在Rxjs中通過操作符bufferTime 就可以減少維護(hù)timer的成本:
比如我們需要監(jiān)聽頁面滾動的事件,作出一些邏輯操作,這是就會產(chǎn)生事件過于頻繁的調(diào)用,造成頁面卡頓的現(xiàn)象。用原生js實現(xiàn)的時候,需要實現(xiàn)個節(jié)流或者防抖函數(shù),通過實現(xiàn)個閉包函數(shù),在內(nèi)部維護(hù)個定時器。而在Rxjs中通過操作符debounce 就可以方便的解決
評論