自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

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

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

記得當(dāng)年我剛學(xué) JavaScript 的時(shí)候,是從原生的 dom api 學(xué)起的,用原生的 dom api 完成一些增刪改的功能,之后就會學(xué)習(xí) JQuery。

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

創(chuàng)建一個(gè) p 標(biāo)簽包含一個(gè)文本節(jié)點(diǎn),然后插入到 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 當(dāng)年那么火的原因。

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

那 JQuery 做了什么呢?

JQuery 把 dom 封裝了一層,提供了很多操作 dom 的 api,并且支持鏈?zhǔn)秸{(diào)用,可以方便的組織 dom 操作邏輯,而且還支持插件來自定義一些方法在鏈?zhǔn)秸{(diào)用中使用。

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

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

確實(shí)有這樣的一個(gè)庫,就是 Rx.js。

寫 JQuery 的時(shí)候我們是把 dom 封裝了一層,比如 const $container = $(dom),這樣就能用 JQuery 內(nèi)置的工具函數(shù)或者通過插件擴(kuò)展的一些函數(shù),通過鏈?zhǔn)秸{(diào)用把邏輯串起來。

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

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

也就是把 Event Listener、Promise、回調(diào)函數(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 一樣。

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

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

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

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

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

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

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

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

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

這些處理邏輯叫做 Observer。

這就是 RxJs 做的事情了。因?yàn)楫惒竭壿嬍菍δ硞€(gè)事件的響應(yīng),這也叫做響應(yīng)式編程。

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

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

// 多個(gè)數(shù)據(jù)
const observable$ = Rx.Observable.of(1, 2, 3);
// 數(shù)組中的多個(gè)數(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 是可以在外部調(diào)用 next 來產(chǎn)生數(shù)據(jù)的,而 new Observable 是在回調(diào)函數(shù)內(nèi)調(diào)用 next 產(chǎn)生數(shù)據(jù)。

我們小結(jié)一下:

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

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

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

<div @click="clickHandler">點(diǎn)我</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)建個(gè) Observale,就可以把異步邏輯的編寫轉(zhuǎn)變?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)建了個(gè) Observable 對象,每次點(diǎn)擊都調(diào)用 next 產(chǎn)生一個(gè)數(shù)據(jù),傳入處理管道。

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

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

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

總結(jié)

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

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

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

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

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

責(zé)任編輯:姜華 來源: 神光的編程秘籍
相關(guān)推薦

2011-10-12 06:09:32

Dart

2016-12-04 16:36:18

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

2018-05-15 16:13:40

機(jī)器學(xué)習(xí)

2016-01-08 13:07:11

SDN安全SOC安全操作中心

2018-07-09 15:40:04

IOT機(jī)器學(xué)習(xí)應(yīng)用

2022-04-24 16:39:06

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

2014-01-13 09:08:50

云計(jì)算云安全

2011-11-28 13:07:45

WindowsPhonAndroid

2014-05-15 11:41:32

2025-02-07 08:32:56

AI場景Oracle

2012-02-02 17:30:42

2020-12-01 14:51:20

邊緣計(jì)算

2019-11-14 16:17:04

區(qū)塊鏈信息安全

2015-06-24 16:03:24

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

2015-08-17 15:49:49

移動(dòng)技術(shù)大數(shù)據(jù)云計(jì)算

2013-08-20 10:11:20

Go系統(tǒng)管理員

2011-03-11 11:42:19

SAPSaaS云計(jì)算

2020-10-19 15:39:34

人工智能

2022-11-14 15:06:16

2015-11-09 10:18:35

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號