RxJS基礎(chǔ)篇

<H3> 關(guān)于RxJS </H3>

RxJSReactive Extensions for JavaScript 的縮寫立由,起源于 Reactive Extensions,是一個(gè)基于可觀測(cè)數(shù)據(jù)流在異步編程應(yīng)用中的庫褪尝。它提供了一個(gè)核心類型 Observable,附屬類型 (Observer、 Schedulers璃哟、 Subjects) 和操作符Operators缰猴,通過使用 observable 序列來編寫異步和基于事件的程序产艾。ReactiveX 結(jié)合了觀察者模式、迭代器模式和使用集合的函數(shù)式編程滑绒,以滿足用一種理想方式來管理事件序列所需要的一切闷堡。

<H3> 一些前置知識(shí)點(diǎn)梳理 </H3>

  1. 響應(yīng)式編程(RP —— Reactive Programming)
    響應(yīng)式編程是一種面向數(shù)據(jù)流和變化傳播的編程范式。在編程語言中很方便地表達(dá)靜態(tài)或動(dòng)態(tài)的數(shù)據(jù)流疑故,而相關(guān)的計(jì)算模型會(huì)自動(dòng)將變化的值通過數(shù)據(jù)流進(jìn)行傳播杠览。—— 維基百科

    • 響應(yīng)式編程是使用異步數(shù)據(jù)流進(jìn)行編程纵势。常見的異步數(shù)據(jù)流包含事件總線(Event buses)踱阿。用包含這些事件在內(nèi)的任何東西創(chuàng)建數(shù)據(jù)流(Data stream),監(jiān)聽他并作出響應(yīng)钦铁。
    • 只關(guān)注業(yè)務(wù)邏輯互相依賴的事件而不是實(shí)現(xiàn)細(xì)節(jié)软舌。
    • 適用于大量和數(shù)據(jù)有關(guān)的事件交互,特別是高實(shí)時(shí)性要求牛曹。

    舉個(gè)例子佛点,React/Vue的設(shè)計(jì)理念也是一種響應(yīng)式編程范式,我們?cè)诰帉懘a的過程中黎比,不必關(guān)注Dom相關(guān)的操作恋脚,只需要關(guān)注數(shù)據(jù)的變化腺办。React/Vue會(huì)感知到數(shù)據(jù)的變化,并將這種隨著數(shù)據(jù)變化相應(yīng)的Dom層的修改自動(dòng)改變糟描、重新渲染怀喉。

  2. 流(Stream)
    作為響應(yīng)式編程的核心,流的本質(zhì)是一系列隨時(shí)間到達(dá)的數(shù)據(jù)船响。例如:事件流躬拢、直播數(shù)據(jù)流、文本編輯流见间、WebSocket聊闯。

    舉個(gè)例子,代碼中每1s輸出一個(gè)數(shù)字米诉,用戶每一次對(duì)元素的點(diǎn)擊菱蔬,就像是在時(shí)間這個(gè)維度上,產(chǎn)生了一個(gè)數(shù)據(jù)集史侣。這個(gè)數(shù)據(jù)集不像數(shù)組那樣拴泌,它不是一開始都存在的,而是隨著時(shí)間的流逝惊橱,一個(gè)一個(gè)數(shù)據(jù)被輸出出來蚪腐。這種異步行為產(chǎn)生的數(shù)據(jù),就可以被稱之為一個(gè)流税朴,在RxJS中回季,稱之為observable(本質(zhì)上就是一個(gè)數(shù)據(jù)的集合,只是這些數(shù)據(jù)不一定是一開始就設(shè)定好的正林,而是隨著時(shí)間而不斷產(chǎn)生的)泡一。而RxJS,就是為了處理這種流而產(chǎn)生的工具觅廓,比如流與流的合并瘾杭,流的截?cái)啵舆t哪亿,消抖等等操作。

  3. 觀察者模式
    定義對(duì)象間的一種一對(duì)多依賴關(guān)系贤笆,使得每當(dāng)一個(gè)對(duì)象狀態(tài)發(fā)生改變時(shí)蝇棉,其相關(guān)依賴對(duì)象皆得到通知并被自動(dòng)更新。
    [圖片上傳失敗...(image-f20eb2-1638425299670)]

    • 優(yōu)點(diǎn):降低了目標(biāo)與觀察者之間的耦合關(guān)系芥永,兩者之間是抽象耦合關(guān)系篡殷;目標(biāo)與觀察者之間建立了一套觸發(fā)機(jī)制;支持一對(duì)多廣播通信埋涧。
    • 缺點(diǎn):目標(biāo)與觀察者之間的依賴關(guān)系并沒有完全解除板辽,會(huì)出現(xiàn)循環(huán)引用奇瘦;觀察層級(jí)較深時(shí),廣播通信成本高劲弦。
  4. 迭代器模式
    在面向?qū)ο缶幊汤锒辏髂J绞且环N設(shè)計(jì)模式,是一種最簡單也最常見的設(shè)計(jì)模式邑跪。迭代器模式可以把迭代的過程從從業(yè)務(wù)邏輯中分離出來次坡,它可以讓用戶透過特定的接口訪問容器中的每一個(gè)元素而不用了解底層的實(shí)現(xiàn)。

    const iterable = [1, 2, 3];
    const iterator = iterable[Symbol.iterator]();
    iterator.next(); // => { value: "1", done: false}
    iterator.next(); // => { value: "2", done: false}
    iterator.next(); // => { value: "3", done: false}
    iterator.next(); // => { value: undefined, done: true}
    

    由上可知Iterator 只有一個(gè) next 方法画畅,通過調(diào)用 next 獲取值砸琅。
    作為前端開發(fā)者來說,我們最常遇到的部署了Iterator接口的數(shù)據(jù)結(jié)構(gòu)有:Map轴踱、Set症脂、Array、類數(shù)組等等淫僻,我們?cè)谑褂盟麄兊倪^程中诱篷,均能使用同一個(gè)接口訪問每個(gè)元素就是運(yùn)用了迭代器模式。
    Iterator作用:

    • 為各種數(shù)據(jù)結(jié)構(gòu)嘁傀,提供一個(gè)統(tǒng)一的兴蒸、簡便的訪問接口;
    • 使得數(shù)據(jù)結(jié)構(gòu)的成員能夠按某種次序排列细办;
    • 為新的遍歷語法 for...of 實(shí)現(xiàn)循環(huán)遍歷

<H3> RxJS中的核心概念 </H3>

  1. Observable (可觀察對(duì)象): RxJS是觀察者 + 迭代器模式的結(jié)合橙凳,Observable作為被觀察者,是一個(gè)可調(diào)用的未來值或事件的集合笑撞。它能被多個(gè)observer訂閱岛啸,每個(gè)訂閱關(guān)系相互獨(dú)立、互不影響茴肥。


    Observables是使用 Rx.Observable.create 或創(chuàng)建操作符創(chuàng)建的坚踩,并使用Observer(觀察者)來訂閱它,然后執(zhí)行它并發(fā)送 next / error / complete 通知給觀察者瓤狐,而且執(zhí)行可能會(huì)被清理瞬铸。這四個(gè)方面全部編碼在 Observables 實(shí)例中,但某些方面是與其他類型相關(guān)的础锐,像 Observer (觀察者) 和 Subscription (訂閱)嗓节。
    Observable 的核心關(guān)注點(diǎn):

    • 創(chuàng)建 Observables:Rx.Observable.create 是 Observable 構(gòu)造函數(shù)的別名,它接收一個(gè)參數(shù):subscribe 函數(shù)皆警。下面的示例創(chuàng)建了一個(gè) Observable拦宣,它每隔一秒會(huì)向觀察者發(fā)送字符串 'hi' 。
    var observable = Rx.Observable.create(function subscribe(observer) {
        var id = setInterval(() => {
            observer.next('hi')
        }, 1000);
    });
    
    • 訂閱 Observables
      示例中的 Observable 對(duì)象 observable 可以訂閱,像這樣:
    observable.subscribe(x => console.log(x));
    

    訂閱 Observable 像是調(diào)用函數(shù), 并提供接收數(shù)據(jù)的回調(diào)函數(shù)鸵隧。subscribe 調(diào)用是啟動(dòng) “Observable 執(zhí)行”的一種簡單方式绸罗, 并將值或事件傳遞給本次執(zhí)行的觀察者。

    • 執(zhí)行 Observables
      Observable.create(function subscribe(observer) {...}) 中...的代碼表示 “Observable 執(zhí)行”豆瘫,它是惰性運(yùn)算珊蟀,只有在每個(gè)觀察者訂閱后才會(huì)執(zhí)行。隨著時(shí)間的推移靡羡,執(zhí)行會(huì)以同步或異步的方式產(chǎn)生多個(gè)值系洛。
      Observable 執(zhí)行可以傳遞三種類型的值:- "Next" 通知:是最重要,也是最常見的類型略步。發(fā)送一個(gè)值描扯,比如數(shù)字、字符串趟薄、對(duì)象等等绽诚,它們表示傳遞給觀察者的實(shí)際數(shù)據(jù)。- "Error" 通知: 發(fā)送一個(gè) JavaScript 錯(cuò)誤 或 異常杭煎。- "Complete" 通知: 不再發(fā)送任何值恩够。
      在 Observable 執(zhí)行中, 可能會(huì)發(fā)送零個(gè)到無窮多個(gè) "Next" 通知。"Error" 和 "Complete" 可能只會(huì)發(fā)生一次羡铲,并且只會(huì)執(zhí)行其中的一個(gè)蜂桶。如果發(fā)送的是 "Error" 或 "Complete" 通知的話,那么之后不會(huì)再發(fā)送任何通知了也切。
    var observable = Rx.Observable.create(function subscribe(observer) {
        observer.next(1);
        observer.next(2);
        observer.next(3);
        observer.complete();
        observer.next(4); // 因?yàn)檫`反規(guī)約扑媚,所以不會(huì)發(fā)送
    });
    

    Observable 嚴(yán)格遵守自身的規(guī)約,所以下面的代碼不會(huì)發(fā)送 "Next" 通知 4雷恃。

    var observable = Rx.Observable.create(function subscribe(observer) {
        try {
            observer.next(1);
            observer.next(2);
            observer.next(3);
            observer.complete();
        } catch (err) {
            observer.error(err); // 如果捕獲到異常會(huì)發(fā)送一個(gè)錯(cuò)誤
        }
    });
    

    在 subscribe 中可以用 try/catch 代碼塊來包裹任意代碼疆股,如果捕獲到異常的話,會(huì)發(fā)送 "Error" 通知倒槐。

    • 清理 Observables
      因?yàn)?Observable 執(zhí)行可能會(huì)是無限的旬痹,并且觀察者通常希望能在有限的時(shí)間內(nèi)中止執(zhí)行,所以我們需要一個(gè) API 來取消執(zhí)行讨越。因?yàn)槊總€(gè)執(zhí)行都是其對(duì)應(yīng)觀察者專屬的两残,一旦觀察者完成接收值,它必須要一種方法來停止執(zhí)行把跨,以避免浪費(fèi)計(jì)算能力或內(nèi)存資源人弓。
      當(dāng)調(diào)用了 observable.subscribe ,觀察者會(huì)被附加到新創(chuàng)建的 Observable 執(zhí)行中节猿。這個(gè)調(diào)用還返回一個(gè)對(duì)象,即 Subscription (訂閱)。當(dāng)你訂閱(subscribe)了 Observable滨嘱,你會(huì)得到一個(gè) Subscription 峰鄙,它表示進(jìn)行中的執(zhí)行。只要調(diào)用 unsubscribe() 方法就可以取消執(zhí)行太雨。
    var observable = Rx.Observable.from([10, 20, 30]);
    var subscription = observable.subscribe(x => console.log(x));
    // 稍后
    subscription.unsubscribe();
    
  2. Observer (觀察者): Observable 是多個(gè)值的生產(chǎn)者吟榴,并將值 push 給觀察者,觀察者就是由 Observable 發(fā)送的值的消費(fèi)者囊扳。觀察者只是一組回調(diào)函數(shù)的集合吩翻,每個(gè)回調(diào)函數(shù)對(duì)應(yīng)一種 Observable 發(fā)送的通知類型:next、error 和 complete 锥咸。


    一個(gè)典型的觀察者對(duì)象如下所示:

 var observer = {
   next: x => console.log('Observer got a next value: ' + x),
   error: err => console.error('Observer got an error: ' + err),
   complete: () => console.log('Observer got a complete notification'),
};

觀察者只是有三個(gè)回調(diào)函數(shù)的對(duì)象狭瞎,每個(gè)回調(diào)函數(shù)對(duì)應(yīng)一種 Observable 發(fā)送的通知類型。
要使用觀察者搏予,需要把它提供給 Observable 的 subscribe 方法:

var observable = Rx.Observable.create(function (observer) {
 observer.next(1);
 observer.next(2);
 observer.next(3);
 observer.complete();
});
observable.subscribe(observer);
  1. Subscription (訂閱): 表示 Observable 的執(zhí)行熊锭。Subscription 有一個(gè)重要的方法,即 unsubscribe雪侥,它不需要任何參數(shù)碗殷,只是用來清理由 Subscription 占用的資源主要用于取消 Observable 的執(zhí)行。

  2. Operators (操作符): 是 Observable 類型上的方法速缨,比如 .map(...)锌妻、.filter(...)、.merge(...)旬牲,等等仿粹。當(dāng)操作符被調(diào)用時(shí),它們不會(huì)改變已經(jīng)存在的Observable實(shí)例引谜。相反牍陌,它們返回一個(gè)新的Observable,它的subscription邏輯基于第一個(gè) Observable员咽。
    操作符本質(zhì)上是一個(gè)純函數(shù) (pure function)第练,它接收一個(gè) Observable 作為輸入,并生成一個(gè)新的 Observable 作為輸出做瞪。
    要解釋操作符是如何工作的畸裳,文字描述通常是不足以描述清楚的。許多操作符都是跟時(shí)間相關(guān)的滑频,它們可能會(huì)以不同的方式延遲(delay)捡偏、取樣(sample)、節(jié)流(throttle)或去抖動(dòng)值(debonce)峡迷。圖表通常是更適合的工具银伟。彈珠圖是操作符運(yùn)行方式的視覺表示你虹,其中包含輸入 Obserable(s) (輸入可能是多個(gè) Observable )、操作符及其參數(shù)和輸出 Observable 彤避。


    官網(wǎng)操作符:https://cn.rx.js.org/manual/overview.html#h213
    彈珠圖:https://rxmarbles.com/

  3. Subject (主體): RxJS Subject 是一種特殊類型的 Observable傅物,它允許將值多播給多個(gè)觀察者,所以 Subject 是多播的琉预,而普通的 Observables 是單播的(每個(gè)已訂閱的觀察者都擁有 Observable 的獨(dú)立執(zhí)行)董饰。

    • 每個(gè) Subject 都是 Observable:對(duì)于 Subject,你可以提供一個(gè)觀察者并使用 subscribe 方法圆米,就可以開始正常接收值卒暂。從觀察者的角度而言,它無法判斷 Observable 執(zhí)行是來自普通的 Observable 還是 Subject 娄帖。
      在下面的示例中也祠,我們?yōu)?Subject 添加了兩個(gè)觀察者,然后給 Subject 提供一些值:
    var subject = new Rx.Subject();
    
    subject.subscribe({
    next: (v) => console.log('observerA: ' + v)
    });
    subject.subscribe({
    next: (v) => console.log('observerB: ' + v)
    });
    
    subject.next(1);
    subject.next(2);
    // observerA: 1
    // observerB: 1
    // observerA: 2
    // observerB: 2
    
    • 每個(gè) Subject 都是觀察者:Subject 是一個(gè)有如下方法的對(duì)象: next(v)块茁、error(e) 和 complete() 齿坷。要給 Subject 提供新值,只要調(diào)用 next(theValue)数焊,它會(huì)將值多播給已注冊(cè)監(jiān)聽該 Subject 的觀察者們永淌。
      因?yàn)?Subject 是觀察者,這也就在意味著你可以把 Subject 作為參數(shù)傳給任何 Observable 的 subscribe 方法佩耳,如下面的示例所展示:
    var subject = new Rx.Subject();
    
    subject.subscribe({
    next: (v) => console.log('observerA: ' + v)
    });
    subject.subscribe({
    next: (v) => console.log('observerB: ' + v)
    });
    
    var observable = Rx.Observable.from([1, 2, 3]);
    
    observable.subscribe(subject);
    // observerA: 1
    // observerB: 1
    // observerA: 2
    // observerB: 2
    // observerA: 3
    // observerB: 3
    

    使用上面的方法遂蛀,我們基本上只是通過 Subject 將單播的 Observable 執(zhí)行轉(zhuǎn)換為多播的。這也說明了 Subjects 是將任意 Observable 執(zhí)行共享給多個(gè)觀察者的唯一方式干厚。

  4. Schedulers (調(diào)度器): 調(diào)度器控制著何時(shí)啟動(dòng) subscription 和何時(shí)發(fā)送通知李滴。它由三部分組成:

    • 調(diào)度器是一種數(shù)據(jù)結(jié)構(gòu)。 它知道如何根據(jù)優(yōu)先級(jí)或其他標(biāo)準(zhǔn)來存儲(chǔ)任務(wù)和將任務(wù)進(jìn)行排序蛮瞄。
    • 調(diào)度器是執(zhí)行上下文所坯。 它表示在何時(shí)何地執(zhí)行任務(wù)(舉例來說,立即的挂捅,或另一種回調(diào)函數(shù)機(jī)制(比如 setTimeout 或 process.nextTick)芹助,或動(dòng)畫幀)。
    • 調(diào)度器有一個(gè)(虛擬的)時(shí)鐘闲先。 調(diào)度器功能通過它的 getter 方法 now() 提供了“時(shí)間”的概念状土。在具體調(diào)度器上安排的任務(wù)將嚴(yán)格遵循該時(shí)鐘所表示的時(shí)間。
      舉例如下:
var observable = Rx.Observable.create(function (observer) {
 observer.next(1);
 observer.next(2);
 observer.next(3);
 observer.complete();
})
.observeOn(Rx.Scheduler.async); // 調(diào)度控制

console.log('just before subscribe');
observable.subscribe({
 next: x => console.log('got value ' + x),
 error: err => console.error('something wrong occurred: ' + err),
 complete: () => console.log('done'),
});
console.log('just after subscribe');
// just before subscribe
// just after subscribe
// got value 1
// got value 2
// got value 3
// done

從打印結(jié)果上來看伺糠,數(shù)據(jù)的發(fā)送時(shí)機(jī)的確已經(jīng)由同步變成了異步蒙谓,如果不進(jìn)行調(diào)度方式修改,那么“just after subscribe”的打印應(yīng)該是在數(shù)據(jù)發(fā)送完畢之后才會(huì)執(zhí)行的训桶。

<H3> RxJS可以解決什么問題 </H3>

  1. 同步和異步的統(tǒng)一:RxJS 提供了功能非常強(qiáng)大且復(fù)雜的操作符( Operator) 用來處理累驮、組合 Observable酣倾,因此 RxJS 擁有十分強(qiáng)大的異步處理能力,幾乎可以滿足任何異步邏輯的需求谤专,同步邏輯更不在話下灶挟。它也抹平了同步和異步之間的鴻溝。
  2. 可組合的數(shù)據(jù)變更過程
  3. 數(shù)據(jù)和視圖的精確綁定:RxJS 的精髓在于推送數(shù)據(jù)毒租。組件不需要寫請(qǐng)求數(shù)據(jù)和更新數(shù)據(jù)的兩套邏輯,只要訂閱一次箱叁,就能得到現(xiàn)在和將來的數(shù)據(jù)墅垮,如此一來,就能更好地解耦視圖層和數(shù)據(jù)層的邏輯耕漱。視圖層從此不用再操心任何有關(guān)獲取數(shù)據(jù)和更新數(shù)據(jù)的邏輯算色,只要從數(shù)據(jù)層訂閱一次就可以獲取到所有數(shù)據(jù),從而可以只專注于視圖層本身的邏輯螟够。
  4. 條件變更之后的自動(dòng)重新計(jì)算

<H3> RxJS的使用 </H3>

示例一灾梦、控制一秒鐘內(nèi)最多點(diǎn)擊一次

// js版本
var count = 0;
var rate = 1000;
var lastClick = Date.now() - rate;
var button = document.querySelector('button');
button.addEventListener('click', () => {
  if (Date.now() - lastClick >= rate) {
    console.log(`Clicked ${++count} times`);
    lastClick = Date.now();
  }
});
// Rxjs版本
import { Observable } from 'rxjs';
var button = document.querySelector('button');
Observable.fromEvent(button, 'click')
  .throttleTime(1000)
  .scan((count: number) => count + 1, 0)
  .subscribe(count => console.log(`Clicked ${count} times`));

示例二、控制最大并發(fā)數(shù):- 要求最大并發(fā)數(shù) maxNum妓笙;- 每當(dāng)有一個(gè)請(qǐng)求返回若河,就留下一個(gè)空位,可以增加新的請(qǐng)求寞宫;- 所有請(qǐng)求完成后萧福,結(jié)果按照 urls 里面的順序依次打出

import { Observable } from 'rxjs';
// import 'rxjs/add/operator/mergeMap';

// 假設(shè)這是你的http請(qǐng)求函數(shù)
function httpGet(url: string): Promise<string> {
  return new Promise(resolve =>
    setTimeout(() => resolve(`Result: ${url}`), 2000)
  );
}

const array = [
  'https://httpbin.org/ip',
  'https://httpbin.org/user-agent',
  'https://httpbin.org/delay/3',
  'https://httpbin.org/abnet',
  'https://httpbin.org/s',
];

// mergeMap是專門用來處理并發(fā)處理的rxjs操作符
// mergeMap第二個(gè)參數(shù)2的意思是,from(array)每次并發(fā)量是2辈赋,只有promise執(zhí)行結(jié)束才接著取array里面的數(shù)據(jù)
// mergeMap第一個(gè)參數(shù)httpGet的意思是每次并發(fā)鲫忍,從from(array)中取的數(shù)據(jù)如何包裝,這里是作為httpGet的參數(shù)
const source = Observable.from(array)
  .mergeMap(httpGet, 2)
  .subscribe(val => console.log(val));

示例三钥屈、請(qǐng)求依賴并發(fā):發(fā)起一個(gè)用戶登錄請(qǐng)求悟民,成功后再發(fā)送3個(gè)查詢請(qǐng)求(資料,郵件,消息),最后將結(jié)果合并輸出結(jié)果篷就。

import { Observable } from 'rxjs';
const loginRequest = new Promise((resolve, reject) => {
    setTimeout(function () {
        resolve({sessionId:'xxx-xxx-xxx'})
    }, 2000);
});
const queryInfoRequest = function (sessionId) {
    return new Promise((resolve, reject) => {
            setTimeout(function () {
                resolve({
                    id:1,
                    nickName:'lake'
                })
            }, 1000)
        }
    )
};
const queryEmailRequest = function (sessionId) {
    return new Promise((resolve, reject) => {
            setTimeout(function () {
                resolve([
                    {id:1,title:'hi',content:'I miss you'},
                    {id:2,title:'are you there',content:'how are you doing'}
                    ])
            }, 1000)
        }
    )
};
const queryMessageRequest = function (sessionId) {
    return new Promise((resolve, reject) => {
            setTimeout(function () {
                resolve([
                    {id:1,type:'TEXT',content:'I am ok'},
                    {id:2,type:'TEXT',content:'yeah'}
                ])
            }, 1000)
        }
    )
};
const oldTime = new Date().getTime();
Observable.fromPromise(loginRequest)
    .flatMap(sessionId=>{
        return [
            Observable.fromPromise(queryInfoRequest(sessionId)),
            Observable.fromPromise(queryEmailRequest(sessionId)),
            Observable.fromPromise(queryMessageRequest(sessionId)),
        ];
    })
    .combineAll()
    .subscribe(value => {
        console.log(value);
        console.log("總運(yùn)行時(shí)長:"+(new Date() - oldTime));
    });

<H3> 總結(jié) </H3>

  1. 異步操作和同步操作最大的區(qū)別就是異步有時(shí)序射亏。我們可以把同步操作理解為:數(shù)據(jù)+函數(shù);那么異步操作就是:數(shù)據(jù)+函數(shù)+時(shí)序腻脏。RxJS做的事情就是把時(shí)序抽離成一根時(shí)間軸鸦泳,在這根時(shí)間軸上進(jìn)行同步操作,而異步相關(guān)的時(shí)序處理就交給Rx提供的各種operator永品。所以如果你的應(yīng)用是一個(gè)時(shí)序密集的應(yīng)用做鹰,那么使用Rx能幫你理清楚復(fù)雜的異步邏輯。反之鼎姐,如果異步操作之間沒有太多的聯(lián)系钾麸,時(shí)序簡單更振,則不那么需要使用RxJS。
  2. RxJS 最核心的地方也不是一堆花哨的操作符饭尝,而是它的響應(yīng)式的思想肯腕,它是能改變你整個(gè)編程思路的東西。如果僅僅是用 RxJS 來解決應(yīng)用中的一些孤立的異步場景钥平,比如拖拽实撒、節(jié)流之類的,用 RxJS 是有點(diǎn)大材小用了涉瘾。因?yàn)槟悴挥?RxJS 也可以實(shí)現(xiàn)知态,頂多就是沒有 RxJS 優(yōu)雅而已。最能夠體現(xiàn) RxJS 威力的還是那些有大量的異步數(shù)據(jù)更新立叛,數(shù)據(jù)之間還互相有依賴關(guān)系的大型前端應(yīng)用负敏。這種場景下,你甚至可以基于 RxJS 設(shè)計(jì)一整套數(shù)據(jù)管理的方案秘蛇,當(dāng)然也不要給本不適合RxJS理念的場景強(qiáng)加使用其做,這樣實(shí)際帶來的效果可能并不明顯。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末赁还,一起剝皮案震驚了整個(gè)濱河市妖泄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌艘策,老刑警劉巖浮庐,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異柬焕,居然都是意外死亡审残,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門斑举,熙熙樓的掌柜王于貴愁眉苦臉地迎上來搅轿,“玉大人,你說我怎么就攤上這事富玷¤捣兀” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵赎懦,是天一觀的道長雀鹃。 經(jīng)常有香客問我,道長励两,這世上最難降的妖魔是什么黎茎? 我笑而不...
    開封第一講書人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮当悔,結(jié)果婚禮上傅瞻,老公的妹妹穿的比我還像新娘踢代。我一直安慰自己,他們只是感情好嗅骄,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開白布胳挎。 她就那樣靜靜地躺著,像睡著了一般溺森。 火紅的嫁衣襯著肌膚如雪慕爬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評(píng)論 1 290
  • 那天屏积,我揣著相機(jī)與錄音澡罚,去河邊找鬼。 笑死肾请,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的更胖。 我是一名探鬼主播铛铁,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼却妨!你這毒婦竟也來了饵逐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤彪标,失蹤者是張志新(化名)和其女友劉穎倍权,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捞烟,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡薄声,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了题画。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片默辨。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖苍息,靈堂內(nèi)的尸體忽然破棺而出缩幸,到底是詐尸還是另有隱情,我是刑警寧澤竞思,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布表谊,位于F島的核電站,受9級(jí)特大地震影響盖喷,放射性物質(zhì)發(fā)生泄漏爆办。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一课梳、第九天 我趴在偏房一處隱蔽的房頂上張望押逼。 院中可真熱鬧步藕,春花似錦、人聲如沸挑格。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽漂彤。三九已至雾消,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間挫望,已是汗流浹背立润。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留媳板,地道東北人桑腮。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像蛉幸,于是被迫代替她去往敵國和親破讨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

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