30 天精通 RxJS (01):認(rèn)識(shí) RxJS

RxJS Logo

這是【30天精通 RxJS】的 01 篇破婆,如果還沒(méi)看過(guò) 00 篇可以往這邊走:
30 天精通 RxJS (00): 關(guān)于本系列文章

在網(wǎng)頁(yè)的世界存取任何資源都是非同步(Async)的劳闹,比如說(shuō)我們希望拿到一個(gè)檔案,要先發(fā)送一個(gè)請(qǐng)求耘戚,然后必須等到檔案回來(lái)嗡髓,再執(zhí)行對(duì)這個(gè)檔案的操作。這就是一個(gè)非同步的行為收津,而隨著網(wǎng)頁(yè)需求的複雜化饿这,我們所寫(xiě)的 JavaScript 就有各種針對(duì)非同步行為的寫(xiě)法浊伙,例如使用 callback 或是 Promise 物件甚至是新的語(yǔ)法糖 async/await —— 但隨著應(yīng)用需求愈來(lái)愈複雜,撰寫(xiě)非同步的程式碼仍然非常困難长捧。

非同步常見(jiàn)的問(wèn)題

  • 競(jìng)態(tài)條件 (Race Condition)
  • 記憶體洩漏 (Memory Leak)
  • 複雜的狀態(tài) (Complex State)
  • 例外處理 (Exception Handling)

Race Condition

每當(dāng)我們對(duì)同一個(gè)資源同時(shí)做多次的非同步存取時(shí)嚣鄙,就可能發(fā)生 Race Condition 的問(wèn)題。比如說(shuō)我們發(fā)了一個(gè) Request 更新使用者資料串结,然后我們又立即發(fā)送另一個(gè) Request 取得使用者資料哑子,這時(shí)第一個(gè) Request 和第二個(gè) Request 先后順序就會(huì)影響到最終接收到的結(jié)果不同,這就是 Race Condition肌割。

Memory Leak

Memory Leak 是最常被大家忽略的一點(diǎn)卧蜓。原因是在傳統(tǒng)網(wǎng)站的行為,我們每次換頁(yè)都是整頁(yè)重刷把敞,并重新執(zhí)行 JavaScript弥奸,所以不太需要理會(huì)記憶體的問(wèn)題!但是當(dāng)我們希望將網(wǎng)站做得像應(yīng)用程式時(shí)奋早,這件事就變得很重要盛霎。例如做 SPA (Single Page Application) 網(wǎng)站時(shí),我們是透過(guò) JavaScript 來(lái)達(dá)到切換頁(yè)面的內(nèi)容耽装,這時(shí)如果有對(duì) DOM 注冊(cè)監(jiān)聽(tīng)事件愤炸,而沒(méi)有在適當(dāng)?shù)臅r(shí)機(jī)點(diǎn)把監(jiān)聽(tīng)的事件移除,就有可能造成 Memory Leak掉奄。比如說(shuō)在 A 頁(yè)面監(jiān)聽(tīng) body 的 scroll 事件摇幻,但頁(yè)面切換時(shí),沒(méi)有把 scroll 的監(jiān)聽(tīng)事件移除挥萌。

Complex State

當(dāng)有非同步行為時(shí),應(yīng)用程式的狀態(tài)就會(huì)變得非常複雜枉侧!比如說(shuō)我們有一支付費(fèi)用戶才能播放的影片引瀑,首先可能要先抓取這部影片的資訊,接著我們要在播放時(shí)去驗(yàn)證使用者是否有權(quán)限播放榨馁,而使用者也有可能再按下播放后又立即按了取消憨栽,而這些都是非同步執(zhí)行,這時(shí)就會(huì)各種複雜的狀態(tài)需要處理翼虫。

Exception Handling

JavaScript 的 try/catch 可以捕捉同步的例外屑柔,但非同步的程式就沒(méi)這麼容易,尤其當(dāng)我們的非同步行為很複雜時(shí)珍剑,這個(gè)問(wèn)題就愈加明顯掸宛。

各種不同的 API

我們除了要面對(duì)非同步會(huì)遇到的各種問(wèn)題外,還需要煩惱很多不同的 API

  • DOM Events
  • XMLHttpRequest
  • fetch
  • WebSockets
  • Server Send Events
  • Service Worker
  • Node Stream
  • Timer

上面列的 API 都是非同步的招拙,但他們都有各自的 API 及寫(xiě)法唧瘾!如果我們使用 RxJS措译,上面所有的 API 都可以透過(guò) RxJS 來(lái)處理,就能用同樣的 API 操作 (RxJS 的 API)饰序。

這裡我們舉一個(gè)例子领虹,假如我們想要監(jiān)聽(tīng)點(diǎn)擊事件(click event),但點(diǎn)擊一次之后不再監(jiān)聽(tīng)求豫。

原生 JavaScript

var handler = (e) => {
    console.log(e);
    document.body.removeEventListener('click', handler); // 結(jié)束監(jiān)聽(tīng)
}

// 注冊(cè)監(jiān)聽(tīng)
document.body.addEventListener('click', handler);

使用 Rx 大概的樣子

Rx.Observable
    .fromEvent(document.body, 'click') // 注冊(cè)監(jiān)聽(tīng)
    .take(1) // 只取一次
    .subscribe(console.log);

JSbin | JSFiddle
(點(diǎn)擊畫(huà)面后會(huì)在 console 顯示塌衰,記得打開(kāi) console 來(lái)看)

大致上能看得出來(lái)我們?cè)谑褂?RxJS 后,不管是針對(duì) DOM Event 還是上面列的各種 API 我們都可以透過(guò) RxJS 的 API 來(lái)做資料操作蝠嘉,像是范例中用 take(n) 來(lái)設(shè)定只取一次最疆,之后就釋放記憶體。

說(shuō)了這麼多是晨,其實(shí)就是簡(jiǎn)單一句話

在面對(duì)日益複雜的問(wèn)題肚菠,我們需要一個(gè)更好的解決方法。

RxJS 基本介紹

RxJS 是一套藉由 Observable sequences 來(lái)組合非同步行為事件基礎(chǔ)程序的 Library罩缴!

可以把 RxJS 想成處理 非同步行為 的 Lodash蚊逢。

這也被稱為 Functional Reactive Programming,更切確地說(shuō)是指 Functional Programming 及 Reactive Programming 兩個(gè)編程思想的結(jié)合箫章。

RxJS 確實(shí)是 Functional Programming 跟 Reactive Programming 的結(jié)合烙荷,但能不能稱為 Functional Reactive Programming (FRP) 一直有爭(zhēng)議。

Rx 在官網(wǎng)上特別指出檬寂,有時(shí)這會(huì)被稱為 FRP 但這其實(shí)是個(gè)“誤稱”终抽。

簡(jiǎn)單說(shuō) FRP 是操作隨著時(shí)間連續(xù)性改變的數(shù)值 而 Rx 則比較像是操作隨著時(shí)間發(fā)出的離散數(shù)值,這個(gè)部份讀者不用分得太細(xì)桶至,因?yàn)?FRP 的定義及解釋一直存在著歧異昼伴,也有眾多大神為此爭(zhēng)論,如下

André Staltz:Rx 著名的推廣者镣屹,也是 RxJS 5 主要貢獻(xiàn)者之一圃郊,同時(shí)是 Cycle.js 的作者。Staltz 特別寫(xiě)了一篇文章解釋為什麼 Rx 不能說(shuō)是 FRP 但他仍然稱其為 FRP女蜈。

Juan Gomez:曾在 Netflix 工作持舆,目前任職于 Fitbit,經(jīng)常出現(xiàn)在國(guó)外演討會(huì)伪窖,主要寫(xiě) Android逸寓。Juan Gomez 在 Droidcon NYC 2015 的演講中特別提出他堅(jiān)持稱 Rx 為 FRP。

Evan Czaplicki:任職于 NoRedInk覆山,Elm 的作者竹伸。Evan 在 StrangeLoop 2014 的演講中,特別為現(xiàn)在各種 FRP 的不同解釋做分類汹买。

筆者自己的看法是比較偏向直接稱 Rx 為 FRP佩伤,原因是這較為直覺(jué)(FP + RP = FRP)聊倔,也比較不會(huì)對(duì)新手造成困惑,另外就是其他各種編程范式(包含 OOP, FP)其實(shí)都是想法的集合生巡,而非嚴(yán)格的指南(Guideline)耙蔑,我們應(yīng)該更寬鬆的看待 FRP 而不是給他一個(gè)嚴(yán)格的定義。

關(guān)于 Reactive Extension (Rx)

Rx 最早是由微軟開(kāi)發(fā)的 LinQ 擴(kuò)展出來(lái)的開(kāi)源專案孤荣,之后主要由社群的工程師貢獻(xiàn)甸陌,有多種語(yǔ)言支援,也被許多科技公司所採(cǎi)用盐股,如 Netflix, Trello, Github, Airbnb...等钱豁。

Rx 的相關(guān)資訊

  • 開(kāi)源專案 (Apache 2.0 License)
  • 多種語(yǔ)言支持
    • JavaScript
    • Java
    • C#
    • Python
    • Ruby
    • ...(太多了列不完)
  • 官網(wǎng)
  • 微軟目前最成功的開(kāi)源專案

LinQ 唸做 Link,全名是 Language-Integrated Query疯汁,其功能很多元也非常強(qiáng)大牲尺;學(xué) RxJS 可以不用會(huì)。

Functional Reactive Programming

Functional Reactive Programming 是一種編程范式(programming paradigm)幌蚊,白話就是一種寫(xiě)程式的方法論谤碳!舉個(gè)例子,像 OOP 就是一種編程范式溢豆,OOP 告訴我們要使用物件的方式來(lái)思考問(wèn)題蜒简,以及撰寫(xiě)程式。而 Functional Reactive Programming 其實(shí)涵蓋了 Reactive Programming 及 Functional Programming 兩種編程思想漩仙。

Functional Programming

Functional Programming 大部分的人應(yīng)該多少都有接觸過(guò)搓茬,這也是 Rx 學(xué)習(xí)過(guò)程中的重點(diǎn)之一,我們之后會(huì)花兩天的篇幅來(lái)細(xì)講 Functional Programming队他。
如果要用一句話來(lái)總結(jié) Functional Programming卷仑,那就是 用 function 來(lái)思考我們的問(wèn)題,以及撰寫(xiě)程式

在下一篇文章會(huì)更深入的講解 Functional Programming

Reactive Programming

很多人一談到 Reactive Programming 就會(huì)直接聯(lián)想到是在講 RxJS麸折,但實(shí)際上 Reactive Programming 仍是一種編程范式系枪,在不同的場(chǎng)景都有機(jī)會(huì)遇到,而非只存在于 RxJS磕谅,尤雨溪(Vue 的作者)就曾在 twitter 對(duì)此表達(dá)不滿!


Evan You 的推文

Reactive Programming 簡(jiǎn)單來(lái)說(shuō)就是 當(dāng)變數(shù)或資源發(fā)生變動(dòng)時(shí)雾棺,由變數(shù)或資源自動(dòng)告訴我發(fā)生變動(dòng)了

這句話看似簡(jiǎn)單膊夹,其實(shí)背后隱含兩件事

  • 當(dāng)發(fā)生變動(dòng) => 非同步:不知道什麼時(shí)候會(huì)發(fā)生變動(dòng),反正變動(dòng)時(shí)要跟我說(shuō)
  • 由變數(shù)自動(dòng)告知我 => 我不用寫(xiě)通知我的每一步程式碼

由于最近很紅的 Vue.js 底層就是用 Reactive Programming 的概念實(shí)作捌浩,讓我能很好的舉例放刨,讓大家理解什麼是 Reactive Programming!

當(dāng)我們?cè)谑褂?vue 開(kāi)發(fā)時(shí)尸饺,只要一有綁定的變數(shù)發(fā)生改變进统,相關(guān)的變數(shù)及畫(huà)面也會(huì)跟著變動(dòng)助币,而開(kāi)發(fā)者不需要寫(xiě)這其中如何通知發(fā)生變化的每一步程式碼,只需要專注在發(fā)生變化時(shí)要做什麼事螟碎,這就是典型的 Reactive Programming (記得必須是由變數(shù)或資源主動(dòng)告知眉菱!)

Vue.js 在做 two-ways data binding 是透過(guò) ES5 definedProperty 的 getter/setter。每當(dāng)變數(shù)發(fā)生變動(dòng)時(shí)掉分,就會(huì)執(zhí)行 getter/setter 從而收集有改動(dòng)的變數(shù)俭缓,這也被稱為依賴收集

Rx 基本上就是上述的兩個(gè)觀念的結(jié)合酥郭,這個(gè)部份讀者在看完之后的文章华坦,會(huì)有更深的體悟。

今日小結(jié)

今天這篇文章主要是帶大家了解為什麼我們需要 RxJS不从,以及 RxJS 的基本介紹惜姐。若讀者還不太能吸收本文的內(nèi)容,可以過(guò)一段時(shí)間后再回來(lái)看這篇文章會(huì)有更深的體會(huì)椿息,或是在下方留言給我歹袁!
文章轉(zhuǎn)自[https://ithelp.ithome.com.tw/articles/10186104]

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市撵颊,隨后出現(xiàn)的幾起案子宇攻,更是在濱河造成了極大的恐慌,老刑警劉巖倡勇,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逞刷,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡妻熊,警方通過(guò)查閱死者的電腦和手機(jī)夸浅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)扔役,“玉大人帆喇,你說(shuō)我怎么就攤上這事∫谛兀” “怎么了坯钦?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)侈玄。 經(jīng)常有香客問(wèn)我婉刀,道長(zhǎng),這世上最難降的妖魔是什么序仙? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任突颊,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘律秃。我一直安慰自己爬橡,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布棒动。 她就那樣靜靜地躺著糙申,像睡著了一般。 火紅的嫁衣襯著肌膚如雪迁客。 梳的紋絲不亂的頭發(fā)上郭宝,一...
    開(kāi)封第一講書(shū)人閱讀 52,549評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音掷漱,去河邊找鬼粘室。 笑死,一個(gè)胖子當(dāng)著我的面吹牛卜范,可吹牛的內(nèi)容都是我干的衔统。 我是一名探鬼主播,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼海雪,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼锦爵!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起奥裸,我...
    開(kāi)封第一講書(shū)人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤险掀,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后湾宙,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體樟氢,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年侠鳄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了埠啃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡伟恶,死狀恐怖碴开,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情博秫,我是刑警寧澤潦牛,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站挡育,受9級(jí)特大地震影響罢绽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜静盅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蒿叠,春花似錦明垢、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至施绎,卻和暖如春溯革,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谷醉。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工致稀, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人俱尼。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓抖单,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親遇八。 傳聞我的和親對(duì)象是個(gè)殘疾皇子矛绘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容