javascript
30 天精通 RxJS (01):认识 RxJS
原作者:一名來自臺灣的小伙子,熱愛學(xué)習(xí)新技術(shù),喜歡 JS 與 Functional Programming,熱衷於把困難的技術(shù)用簡單的語言闡述,歡迎來到我的文章。
原文
在網(wǎng)頁中存取數(shù)據(jù)都是異步(Async)的,比如說我們想從后端拿到一組數(shù)據(jù),要先發(fā)送一個請求,然后必須等到數(shù)據(jù)回來,再執(zhí)行對這個數(shù)據(jù)的操作。這就是一個異步的行為,而隨著網(wǎng)頁需求的復(fù)雜化,我們所寫的 JavaScript 就有各鐘針對異步行為的寫法,例如使用 callback 或是 Promise 對象甚至是新的語法糖 async/await —— 但隨著應(yīng)用需求越來越復(fù)雜,撰寫非同步的代碼仍然非常困難。
異步常見的問題
- 竟態(tài)條件 (Race Condition)
- 內(nèi)存泄漏 (Memory Leak)
- 復(fù)雜的狀態(tài) (Complex State)
- 異常處理 (Exception Handling)
Race Condition
當我們對同一個資源同時做多次的異步存取時,就可能發(fā)生 Race Condition 的問題。比如說我們發(fā)了一個 Request 更新使用者資料,然后我們又立即發(fā)送另一個 Request 取得使用者資料,這時第一個 Request 和第二個 Request 先后順序就會影響到最終接收到的結(jié)果不同,這就是 Race Condition。
Memory Leak
Memory Leak 是最常被大家忽略的一點。原因是在傳統(tǒng)網(wǎng)站開發(fā)中,我們每次跳轉(zhuǎn)都是整個頁面重新加載,重新執(zhí)行 JavaScript,所以不太需要關(guān)注內(nèi)存的問題!但是當我們希望將網(wǎng)站做得像軟件時,這件事就變得很重要。例如做 SPA (Single Page Application) 網(wǎng)站時,我們是通過 JavaScript 來達到切換頁面的內(nèi)容,這時如果有對 DOM 注冊監(jiān)聽事件,而沒有在適當?shù)臅r機把監(jiān)聽的事件移除,就有可能造成 Memory Leak。比如說在 A 頁面監(jiān)聽 body 的 scroll 事件,但頁面切換時,沒有把 scroll 的監(jiān)聽事件移除。
Complex State
當有異步行為時,函數(shù)的狀態(tài)就會變得非常復(fù)雜!比如說我們有一個付費用戶才能播放的視頻,首先可能要先獲取這部視頻的信息,接著我們要在播放時去驗證使用者是否有權(quán)限播放,而使用者也有可能再按下播放后又立即按了取消,而這些都是異步執(zhí)行,這時就有會各種復(fù)雜的狀態(tài)需要處理。
Exception Handling
JavaScript的try/catch可以捕捉同步的異常,但異步的程序就沒這么容易,尤其當我們的異步行為很復(fù)雜時,這個問題就愈加明顯。
各種不同的API
我們除了要面對異步會遇到的各種問題外,還需要煩惱很多不同的API
- DOM Events
- XMLHttpRequest
- Fetch
- WebSockets
- Server Send Events
- Service Worker
- Node Stream
- Timer
上面列的API都是異步的,但他們都有各自的API及寫法!如果我們使用RxJS,上面所有的API都可以通過RxJS來處理,就能用同樣的API操作(RxJS的API)。
這里我們舉一個例子,假如我們想要監(jiān)聽點擊事件(click event),但點擊一次之后不再監(jiān)聽。
原生JavaScript
var handler = (e) => {console.log(e);document.body.removeEventListener('click', handler); // 結(jié)束監(jiān)聽 }// 注冊監(jiān)聽 document.body.addEventListener('click', handler); 復(fù)制代碼使用 Rx
Rx.Observable.fromEvent(document.body, 'click') // 注冊監(jiān)聽.take(1) // 只取一次.subscribe(console.log); 復(fù)制代碼大致上能看得出來我們在使用RxJS后,不管是針對DOM Event還是上面列的各種API我們都可以通過RxJS的API來做數(shù)據(jù)操作,示例中用 take(n)來設(shè)定只取一次,之后就釋放內(nèi)存。
說了這么多,其實就是簡單一句話
在面對日益復(fù)雜的問題,我們需要一個更好的解決方法。
RxJS 基本介紹
RxJS是一套由Observable sequences來組合異步行為和事件基礎(chǔ)函數(shù)的Library!
可以把RxJS想成處理異步行為的Lodash。
也可以被稱為Functional Reactive Programming,更切確地說是指Functional Programming及Reactive Programming兩個編程思想的結(jié)合。
RxJS確實是Functional Programming跟Reactive Programming的結(jié)合,但能不能稱為Functional Reactive Programming(FRP)一直有爭議。
Rx在官網(wǎng)上特別指出,有時這會被稱為FRP,但這其實是個“誤稱”。
簡單說FRP是操作隨著時間連續(xù)性改變的數(shù)值,而Rx則比較像是操作隨著時間發(fā)出的離散數(shù)值,這個部份讀者不用分得太細,因為FRP的定義及解釋一直存在著歧異,也有眾多大神為此爭論,如下
AndréStaltz: Rx著名的推廣者,也是RxJS 5主要貢獻者之一,同時是Cycle.js的作者。Staltz特別寫了一篇文章解釋為什么Rx不能說是FRP但他仍然稱其為FRP。
Juan Gomez:曾在Netflix工作,目前任職于Fitbit,經(jīng)常出現(xiàn)在國外演討會,主要寫Android。Juan Gomez在Droidcon NYC 2015的演講中特別提出他堅持稱Rx為FRP。
Evan Czaplicki:任職于NoRedInk,Elm的作者。Evan在StrangeLoop 2014的演講中,特別為現(xiàn)在各種FRP的不同解釋做分類。
關(guān)于Reactive Extension(Rx)
Rx最早是由微軟開發(fā)的LinQ擴展出來的開源項目,之后主要由社區(qū)的工程師貢獻,有多種語言支持,也被許多科技公司所采用,如Netflix,Trello,Github,Airbnb…等。
Functional Reactive Programming
Functional Reactive Programming是一種編程思想(programming paradigm),舉個例子,像OOP就是一種編程思想,OOP告訴我們要使用對象的方式來思考問題,以及編寫程序。而Functional Reactive Programming其實涵蓋了Reactive Programming及Functional Programming兩種編程思想。
Functional Programming
Functional Programming大部分的人應(yīng)該多少都有接觸過,這也是Rx學(xué)習(xí)過程中的重點之一,我們之后會花兩章的篇幅來細講Functional Programming。如果要用一句話來總結(jié)Functional Programming,那就是用function來思考我們的問題,以及撰寫程序
在下一篇文章會更深入的講解Functional Programming
Reactive Programming
很多人一談到Reactive Programming就會直接聯(lián)想到是在講RxJS,但實際上Reactive Programming仍是一種編程思想,在不同的場景都有機會遇到,而非只存在于RxJS,尤雨溪(Vue的作者)就曾在twitter對此表達不滿!
Reactive Programming簡單來說就是當變量或數(shù)據(jù)發(fā)生變化時,由變量或數(shù)據(jù)自動告訴我發(fā)生變動了
這句話看似簡單,其實背后隱含兩件事
-
當發(fā)生變動=>異步:不知道什么時候會發(fā)生變動,反正變動時要跟我說
-
由變量自動告知我=>不用通知我的每一步代碼
由于最近很紅的Vue.js底層就是用Reactive Programming的概念實現(xiàn),能很好的舉例,讓大家理解什么是Reactive Programming!
當我們在使用vue開發(fā)時,只要一有綁定的變量發(fā)生改變,相關(guān)的變量及頁面也會跟著變動,而開發(fā)者不需要寫這其中如何通知發(fā)生變化的每一步代碼,只需要專注在發(fā)生變化時要做什么事,這就是典型的Reactive Programming(記得必須是由變量或數(shù)據(jù)主動告知!)
Vue.js在做two-ways data binding是通過ES5 definedProperty的getter/setter。每當變量發(fā)生變動時,就會執(zhí)行g(shù)etter/setter從而收集有改動的變量,這也被稱為依賴收集。
Rx基本上就是上述的兩個觀念的結(jié)合,這個部份在看完之后的文章,會有更深的體悟。
今日小結(jié)
今天這篇文章主要是帶大家了解為什么我們需要RxJS,以及RxJS的基本介紹。若讀者還不太能吸收本文的內(nèi)容,可以過一段時間后再回來看這篇文章會有更深的體會,或是在下方留言給我!
原文
轉(zhuǎn)載于:https://juejin.im/post/5cd57b5fe51d453b560f2d74
總結(jié)
以上是生活随笔為你收集整理的30 天精通 RxJS (01):认识 RxJS的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 1、集合--相关概述
- 下一篇: cento7.6安装kubernetes