偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

RxJS 之于異步,就像 JQuery 之于Dom

開發(fā) 前端
用原生的 dom api 進行 dom 操作比較繁瑣,所以我們會使用 JQuery,它把 dom 包了一層,提供了很多方便的內置 api,而且還支持通過插件擴展,這樣極大的簡化了 dom 操作。

記得當年我剛學 JavaScript 的時候,是從原生的 dom api 學起的,用原生的 dom api 完成一些增刪改的功能,之后就會學習 JQuery。

剛接觸 JQuery 的時候,感覺這也太爽了吧。比如這樣一段邏輯:

創(chuàng)建一個 p 標簽包含一個文本節(jié)點,然后插入到 container 中。

用原生 dom api 寫是這樣的:

const containerDom = document.getElementById('container');
const textDom = document.createTextNode("Hello World.");
const paraDom = document.createElement("p");
pparaDom.appendChild(textDom);
containerDom.appendChild(paraDom);

而用 JQuery 寫是這樣的:

const $container = $('#container');
$container.append('<p>Hello World.</p>');

比起用原生 dom api 來寫簡化太多了!這也是為什么 JQuery 當年那么火的原因。

雖然現(xiàn)在都用 Vue、React 這種數(shù)據(jù)驅動的前端框架來寫頁面,基本不直接操作 dom 了。但涉及到一些活動頁等需要直接操作 dom 的場景,用 JQuery 依然很方便。

那 JQuery 做了什么呢?

JQuery 把 dom 封裝了一層,提供了很多操作 dom 的 api,并且支持鏈式調用,可以方便的組織 dom 操作邏輯,而且還支持插件來自定義一些方法在鏈式調用中使用。

可能你會說,JQuery 不是基本用不到了么,提它干什么?

因為我覺得 JQuery 對 dom 操作的這層封裝很好,把操作 dom 的復雜度降低了很多。前端除了經(jīng)常操作 dom 外,還會經(jīng)常處理異步,比如 XHR 和 Fetch、Event Listener 等,雖然可以用 Promise 封裝,還可以進一步簡化成 async/await 的寫法,但是 Promise 和 async/await 只是改變了異步邏輯的書寫形式,并沒有降低異步邏輯編寫的復雜度。 能不能就像 JQuery 對 dom 操作的封裝那樣,把異步邏輯也給封裝一層,簡化下異步邏輯的編寫呢?

確實有這樣的一個庫,就是 Rx.js。

寫 JQuery 的時候我們是把 dom 封裝了一層,比如 const $container = $(dom),這樣就能用 JQuery 內置的工具函數(shù)或者通過插件擴展的一些函數(shù),通過鏈式調用把邏輯串起來。

為了和 dom 對象容易區(qū)分,我們會把 JQuery 對象命名成 $、$yy 等。

那么 Rx.js 第一步要做的也是把異步邏輯包一層:

也就是把 Event Listener、Promise、回調函數(shù)這種異步代碼包一層:

// 包一層 Event Listener
const observable$ = Rx.Observable.fromEvent(document.querySelector('button'), 'click');
// 包一層 Promise
const observable2$ = Rx.Observable.fromPromise(fetch('/users'));
// 包一層 callback
const observeable3$ = Rx.Observable.bindCallback(fs.exists);

包裝以后的對象不叫 RxJS 對象,叫做 Observable 對象,而且為了便于區(qū)分,我們會把它命名為 xxx$、$,就像 JQuery 對象我們會命名成 $、$yyy 一樣。

然后就可以用內置的一系列工具函數(shù)了,這些叫做操作符 operator:

observable$.pipe(
throttleTime(300),
take(3),
map(event => event.target.value)
);

比如異步邏輯我們經(jīng)常做節(jié)流處理,那就不用自己寫了,直接用內置的操作符 throttleTime 就行。

還有忽略前三次事件 take(3),對數(shù)據(jù)做一次映射 map(() => xxx) 等等這些常見異步邏輯用操作符來寫就很簡單。

把異步邏輯組織成鏈條(或者叫管道 pipe),用操作符來寫每步的處理邏輯,然后串聯(lián)起來,這樣就把異步邏輯的書寫變?yōu)榱?pipe 的組織。而且就像 JQuery 可以寫插件來擴展一樣,Rxjs 也支持自定義操作符。

經(jīng)過這個管道之后,數(shù)據(jù)經(jīng)過了每一步異步邏輯的處理,我們可以通過 subcribe 監(jiān)聽,拿到最終的數(shù)據(jù)。

observerable$.subscribe((value) => {
// xxx
})

當然,也可能在處理的過程中出錯了,那也要把 error 傳下去,并且最終處理完以后也會有個通知,所以可以寫這樣三種情況的處理:

observerable$.subscribe({
next: (v) => {},
error: (err) =>{},
complete: () => {}
});

這些處理邏輯叫做 Observer。

這就是 RxJs 做的事情了。因為異步邏輯是對某個事件的響應,這也叫做響應式編程。

剛才我們創(chuàng)建 Observable 是包了一層 Event Listener、callback、Promise,當然也可以直接創(chuàng)建這樣一個 Observable 對象:

比如我們把一系列數(shù)封裝成 Observable:

// 多個數(shù)據(jù)
const observable$ = Rx.Observable.of(1, 2, 3);
// 數(shù)組中的多個數(shù)據(jù)
const observable2$ = Rx.Observable.from([1,2,3]);

或者經(jīng)過一些邏輯邏輯產(chǎn)生一系列數(shù)據(jù):

var observable$ = new Rx.Observable(function (observer) {
observer.next(1);
observer.next(2);
observer.next(3);
setTimeout(() => {
observer.next(4);
observer.complete();
}, 1000);
});

或者這樣:

const observable$ = new Rx.Subject(); 
observable$.next(1);
observable$.next(2);

這里的區(qū)別是 Subject 是可以在外部調用 next 來產(chǎn)生數(shù)據(jù)的,而 new Observable 是在回調函數(shù)內調用 next 產(chǎn)生數(shù)據(jù)。

我們小結一下:

就像 JQuery 對 dom 包了一層,然后提供了簡化 dom 操作的 api 一樣,RxJS 也對異步邏輯包裝了一層,然后提供了一系列 operator。我們可以把 EventListenr、Promise、callback 等包裝成 Observable(或者自己用 of、from、Subject 等創(chuàng)建 Observable),然后用內置的或者自己擴展的 oprator 組織處理管道,在管道的末尾用 Observer 接受數(shù)據(jù)、處理錯誤。這樣就把異步邏輯的編寫,轉變?yōu)榱瞬僮鞣艿赖慕M織。當對內置的 operator 足夠熟練或者自己沉淀了一些 operator 之后,寫異步的邏輯速度會變得很快。

因為 RxJS 只是對異步邏輯的封裝,和 Vue、React 等前端框架并不沖突,所以可以很好的結合在一起。(Angular 甚至默認就集成了 RxJS)

比如在 Vue 里面,我們可以把事件用 Subject 封裝成一個 Observable,然后就可以用 RxJS 的操作符來組織異步邏輯了:

<div @click="clickHandler">點我</div>
import { Subject } from 'rxjs'
import { debounceTime } from 'rxjs/operators'

export default {
data() {
return {
observable$: new Subject()
}
},
created() {
this.observable$.pipe(debounceTime(500)).subscribe((event) => {
// xxx
})
},
methods: {
clickHandler(event) {
this.observable$.next(event)
}
}
}

在 React 里面也一樣,用 Subject 自己創(chuàng)建個 Observale,就可以把異步邏輯的編寫轉變?yōu)?operator 的組裝了:

class MyButton extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };

this.observable$ = new Rx.Subject();

this.observable$.pipe(
debounceTime(500),
map(() => 1),
scan((total, num) => total + num, 0)
);

this.observable$.subscribe(x => {
this.setState({ count: x })
})
}
render() {
return <button onClick={event => this.observable$.next(event)}>{
this.state.count
}</button>
}
}

我們用 Subject 創(chuàng)建了個 Observable 對象,每次點擊都調用 next 產(chǎn)生一個數(shù)據(jù),傳入處理管道。

管道我們是用 operator 組織的,先做了 500ms 的截流,然后把值變?yōu)?1,之后計數(shù)。

處理完之后傳遞給 Observer 的就是累加后的數(shù)值,設置到 state 即可。

這樣一段節(jié)流 + 計數(shù)的異步邏輯就寫完了,其實就是組裝了下 operator,這就是 RxJS 的意義。

總結

用原生的 dom api 進行 dom 操作比較繁瑣,所以我們會使用 JQuery,它把 dom 包了一層,提供了很多方便的內置 api,而且還支持通過插件擴展,這樣極大的簡化了 dom 操作。

除了操作 dom,前端開發(fā)還經(jīng)常要寫異步邏輯,同樣也需要這樣一個包一層的庫來簡化,它就是 Rx.js。

Rx.js 把 Event Listener、Promise、callback 等封裝成了 Observable(也可以自己創(chuàng)建),提供了很多操作符 operator(還可以自定義),用它們來組裝成處理管道(pipe)來處理異步邏輯,最后傳入 Observer 來接收數(shù)據(jù)和處理錯誤。這樣把異步邏輯的編寫轉變?yōu)榱?operator 的組裝,把填空題變?yōu)榱诉x擇題,異步邏輯的編寫速度和體驗自然會提升很多。

而且,RxJS 是專門處理異步邏輯的,可以和前端框架很好的結合在一起使用。

就像用 JQuery 操作 dom 很爽一樣,熟悉了 RxJS 的 operator,用 RxJS 編寫(組裝)異步邏輯的體驗很非常棒。

責任編輯:姜華 來源: 神光的編程秘籍
相關推薦

2011-10-12 06:09:32

Dart

2016-12-04 16:36:18

NoSQL數(shù)據(jù)庫大數(shù)據(jù)

2018-07-09 15:40:04

IOT機器學習應用

2016-01-08 13:07:11

SDN安全SOC安全操作中心

2018-05-15 16:13:40

機器學習

2014-01-13 09:08:50

云計算云安全

2011-11-28 13:07:45

WindowsPhonAndroid

2014-05-15 11:41:32

2022-04-24 16:39:06

數(shù)字化轉銀行中臺

2012-02-02 17:30:42

2020-12-01 14:51:20

邊緣計算

2025-02-07 08:32:56

AI場景Oracle

2019-11-14 16:17:04

區(qū)塊鏈信息安全

2011-03-11 11:42:19

SAPSaaS云計算

2015-08-17 15:49:49

移動技術大數(shù)據(jù)云計算

2013-08-20 10:11:20

Go系統(tǒng)管理員

2015-06-24 16:03:24

大數(shù)據(jù).SAS

2020-10-19 15:39:34

人工智能

2022-11-14 15:06:16

2015-11-09 10:18:35

點贊
收藏

51CTO技術棧公眾號