中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Rx響應式編程的原理及應用

發布時間:2021-06-18 14:09:18 來源:億速云 閱讀:185 作者:chen 欄目:開發技術

這篇文章主要介紹“Rx響應式編程的原理及應用”,在日常操作中,相信很多人在Rx響應式編程的原理及應用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Rx響應式編程的原理及應用”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

目錄
  • 一、Observable

  • 二、高階函數

  • 三、快遞盒模型

    • 3.1、快遞盒模型1:fromEvent

    • 3.2、快遞盒模型2:interval

  • 四、高階快遞盒

    • 五、銷毀快遞盒

      • 5.1、銷毀快遞盒——取消訂閱

      • 5.2、銷毀高階快遞盒

    • 六、補充

      • 七、后記

        一、Observable

        Observable從字面翻譯來說叫做“可觀察者”,換言之就是某種“數據源”或者“事件源”,這種數據源具有可被觀察的能力,這個和你主動去撈數據有本質區別。用一個形象的比喻就是Observable好比是水龍頭,你可以去打開水龍頭——訂閱Observable,然后水——數據就會源源不斷流出。這就是響應式編程的核心思想——變主動為被動。不過這個不在本篇文章中詳解。

        Rx響應式編程的原理及應用

        Observable是一種概念,可以通過不同的方式去具體實現,本文通過高階函數來實現兩個常用Observable:fromEvent和Interval。通過講解對Observable的訂閱和取消訂閱兩個行為來幫助讀者真正理解Observable是什么。

        二、高階函數

        高階函數的概念來源于函數式編程,簡單的定義就是一個函數的入參或者返回值是一個函數的函數。例如:

        function foo(arg){
            return function(){
                console.log(arg)
            }
        }
        const bar = foo(“hello world”)
        bar()  // hello world

        ps:高階函數能做的事情很多,這里僅僅針對本文需要的情形進行使用。

        上面這個foo函數的調用并不會直接打印hello world,而只是把這個hello world給緩存起來。后面我們根據實際需要調用返回出來的bar函數,然后真正去執行打印hello world的工作。

        為啥要做這么一步封裝呢?實際上這么做的效果就是“延遲”了調用。而一切的精髓就在這個“延遲”兩個字里面。我們實際上是對一種行為進行了包裝,看上去就像某種一致的東西,好比是快遞盒子。

        Rx響應式編程的原理及應用

        里面可以裝不同的東西,但對于物流來說就是統一的東西。因此,就可以形成對快遞盒的統一操作,比如堆疊、運輸、存儲、甚至是打開盒子這個動作也是一致的。

        回到前面的例子,調用foo函數,相當于打包了一個快遞盒,這個快遞盒里面有一個固定的程序,就是當打開這個快遞盒(調用bar)時執行一個打印操作。

        我們可以有foo1、foo2、foo3……里面有各種各樣的程序,但是這些foos,都有一個共同的操作就是“打開”。(前提是這個foo會返回一個函數,這樣才能滿足“打開”的操作,即調用返回的函數)。

        function foo1(arg){
            return function(){
               console.log(arg+"?")
            }
        }
        function foo2(arg){
              return function(){
                 console.log(arg+"!")
             }
        }
        const bar1 = foo1(“hello world”)
        const bar2 = foo2("yes")
        bar1()+bar2() // hello world? yes!

        三、快遞盒模型

        3.1、快遞盒模型1:fromEvent

        有了上面的基礎,下面我們就來看一下Rx編程中最常用的一個Observable—fromEvent(……)。對于Rx編程的初學者,起初很難理解fromEvent(……)和addEventListener(……)有什么區別。

        btn.addEventListener("click",callback)
        rx.fromEvent(btn,"click").subscribe(callback)

        如果直接執行這個代碼,確實效果是一樣的。那么區別在哪兒呢?最直接的區別是,subscribe函數作用在fromEvent(……)上而不是btn上,而addEventListener是直接作用在btn上的。subscribe函數是某種“打開”操作,而fromEvent(……)則是某種快遞盒。

        fromEvent實際上是對addEventListener的“延遲”調用

        function fromEvent(target,evtName){
            return function(callback){
                target.addEventListener(evtName,callback)
            }
        }
        const ob = fromEvent(btn,"click")
        ob(console.log)// 相當于 subscribe

        哦!fromEvent本質上是高階函數

        至于如何實現subscribe來完成“打開”操作,不在本文討論范圍,在Rx編程中,這個subscribe的動作叫做“訂閱”。“訂閱”就是所有Observable的統一具備的操作。再次強調:本文中對Observable的“調用”在邏輯上相當于subscribe。

        下面再舉一個例子,基本可以讓讀者舉二反N了。

        3.2、快遞盒模型2:interval

        Rx中有一個interval,它和setInterval有什么區別呢?

        估計有人已經開始搶答了,interval就是對setInterval的延遲調用!bingo!

        function interval(period){
            let i = 0
            return function(callback){
                setInterval(period,()=>callback(i++))
            }
        }
        const ob = interval(1000)
        ob(console.log)// 相當于 subscribe

        從上面兩個例子來看,無論是fromEvent(……)還是Interval(……),雖然內部是完全不同的邏輯,但是他們同屬于“快遞盒”這種東西,我們把它稱之為Observable——可觀察者。

        fromEvent和Interval本身只是制作“快遞盒”的模型,只有調用后返回的東西才是“快遞盒”,即fromEvent(btn,"click")、interval(1000) 等等...

        四、高階快遞盒

        有了上面的基礎,下面開始進階:我們擁有了那么多快遞盒,那么就可以對這些快遞盒再封裝。

        Rx響應式編程的原理及應用

        在文章開頭說了,快遞盒統一了一些操作,所以我們可以把許許多多的快遞盒堆疊在一起,即組合成一個大的快遞盒!這個大的快遞盒和小的快遞盒一樣,具有“打開”操作(即訂閱)。當我們打開這個大的快遞盒的時候,會發生什么呢?

        可以有很多種不同的可能性,比如可以逐個打開小的快遞盒(concat),或者一次性打開所有小的快遞盒(merge),也可以只打開那個最容易打開的快遞盒(race)。

        下面是一個簡化版的merge方法:

        function merge(...obs){
            return function(callback){
                obs.forEach(ob=>ob(callback)) // 打開所有快遞盒
            }
        }

        我們還是拿之前的fromEvent和interval來舉例吧!

        Rx響應式編程的原理及應用

        使用merge方法對兩個Observable進行組合:

        const ob1 = fromEvent(btn,'click') // 制作快遞盒1
        const ob2 = interval(1000) // 制作快遞盒2
        const ob = merge(ob1,ob2) //制作大快遞盒
        ob(console.log) // 打開大快遞盒

        當我們“打開”(訂閱)這個大快遞盒ob的時候,其中兩個小快遞盒也會被“打開”(訂閱),任意一個小快遞盒里面的邏輯都會被執行,我們就合并(merge)了兩個Observable,變成了一個。

        這就是我們為什么要辛辛苦苦把各種異步函數封裝成快遞盒(Observable)的原因了——方便對他們進行統一操作!當然僅僅只是“打開”(訂閱)這個操作只是最初級的功能,下面開始進階。

        五、銷毀快遞盒

        5.1、銷毀快遞盒——取消訂閱

        Rx響應式編程的原理及應用

        我們還是以fromEvent為例子,之前我們寫了一個簡單的高階函數,作為對addEventListener的封裝:

        function fromEvent(target,evtName){
            return function(callback){
                target.addEventListener(evtName,callback)
            }
        }

        當我們調用這個函數的時候,就生成了一個快遞盒(fromEvent(btn,'click'))。當我們調用了這個函數返回的函數的時候,就是打開了快遞盒(fromEvent(btn,'click')(console.log))。

        那么我們怎么去銷毀這個打開的快遞盒呢?

        首先我們需要得到一個已經打開的快遞盒,上面的函數調用結果是void,我們無法做任何操作,所以我們需要構造出一個打開狀態的快遞盒。還是使用高階函數的思想:在返回的函數里面再返回一個函數,用于銷毀操作。

        function fromEvent(target,evtName){
            return function(callback){
                target.addEventListener(evtName,callback)
                return function(){
                    target.removeEventListener(evtName,callback)
                }
            }
        }
        const ob = fromEvent(btn,'click') // 制作快遞盒
        const sub = ob(console.log) // 打開快遞盒,并得到一個可用于銷毀的函數
        sub() // 銷毀快遞盒

        同理,對于interval,我們也可以如法炮制:

        function interval(period){
            let i = 0
            return function(callback){
                let id = setInterval(period,()=>callback(i++))
                return function(){
                    clearInterval(id)
                }
            }
        }
        const ob = interval(1000) // 制作快遞盒
        const sub = ob(console.log) // 打開快遞盒
        sub() // 銷毀快遞盒

        5.2、銷毀高階快遞盒

        Rx響應式編程的原理及應用

        我們以merge為例:

        function merge(...obs){
            return function(callback){
                const subs = obs.map(ob=>ob(callback)) // 訂閱所有并收集所有的銷毀函數
                return function(){
                    subs.forEach(sub=>sub()) // 遍歷銷毀函數并執行
                }
            }
        }
         
        const ob1 = fromEvent(btn,'click') // 制作快遞盒1
        const ob2 = interval(1000) // 制作快遞盒2
        const ob = merge(ob1,ob2) //制作大快遞盒
        const sub = ob(console.log) // 打開大快遞盒
        sub() // 銷毀大快遞盒

        當我們銷毀大快遞盒的時候,就會把里面所有的小快遞盒一起銷毀。

        六、補充

        到這里我們已經將Observable的兩個重要操作(訂閱、取消訂閱)講完了,值得注意的是,取消訂閱這個行為并非是作用于Observable上,而是作用于已經“打開”的快遞盒(訂閱Observable后返回的東西)之上!

        Observable除此以外,還有兩個重要操作,即發出事件、完成/異常,(這兩個操作屬于是由Observable主動發起的回調,和操作的方向是相反的,所以其實不能稱之為操作)。

        這個兩個行為用快遞盒就不那么形象了,我們可以將Observable比做是水龍頭,原先的打開快遞盒變成擰開水龍頭,而我們傳入的回調函數就可以比喻成接水的水杯!由于大家對回調函數已經非常熟悉了,所以本文就不再贅述了。

        七、后記

        總結一下我們學習的內容,我們通過高階函數將一些操作進行了“延遲”,并賦予了統一的行為,比如“訂閱”就是延遲執行了異步函數,“取消訂閱”就是在上面的基礎上再“延遲”執行了銷毀資源的函數。

        這些所謂的“延遲”執行就是Rx編程中幕后最難理解,也是最核心的部分。Rx的本質就是將異步函數封裝起來,然后抽象成四大行為:訂閱、取消訂閱、發出事件、完成/異常。

        實際實現Rx庫的方法有很多,本文只是利用了高階函數的思想來幫助大家理解Observable的本質,在官方實現的版本中,Observable這個快遞盒并非是高階函數,而是一個對象,但本質上是一樣的。

        到此,關于“Rx響應式編程的原理及應用”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

        向AI問一下細節

        免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

        AI

        贵德县| 乳山市| 璧山县| 巢湖市| 绥宁县| 秦皇岛市| 大英县| 新蔡县| 垣曲县| 巴里| 通渭县| 龙海市| 岗巴县| 苍南县| 贵定县| 阜新| 云林县| 呼和浩特市| 衢州市| 汉寿县| 京山县| 常宁市| 上林县| 安吉县| 沁源县| 彰化县| 蓬溪县| 舒城县| 建昌县| 巴马| 安远县| 门头沟区| 江口县| 文成县| 赞皇县| 钟山县| 临汾市| 唐河县| 雷波县| 吴桥县| 玉山县|