1. javascript解決異步編程方案
解決javascript異步編程方案有兩種,一種是promise對象形式,還有一種是是Rxjs庫形式,Rxjs相對於Promise來說,有好多Promise沒有的特性和功能,使用起來更便捷簡單;
2. Rxjs 簡單介紹
Rxjs 是Reactive Extensions JavaScript 的簡寫,響應式異步編程;同Promise對象一樣,是解決JS異步編程的一種解決方案;
3. Rxjs使用
1. Rxjs是一個庫,需要使用npm進行安裝;
// 安裝rxjs
npm install rxjs --save
// 安裝rxjs-compat, rxjs-compat軟件包在v5和v6之間創建了一個api兼容層
npm install rxjs-compat --save
2. Rxjs常用操作符
2-1. 創建操作符: fromEvent、 from、 of、 interval、 create
(1). fromEvent: 創建一個 Observable,該 Observable 發出來自給定事件對象的指定類型事件
// 獲取html元素
const btnElem = document.querySelector('button#rxjsBtn');
// 創建按鈕的點擊事件為可觀察對象
Rx.Observable.fromEvent(btnElem, 'click')
.scan(count => count + 1, 0) // count為定義的變量;逗號后面的0為count的初始值;箭頭后面的語句值為scan返回的值;
.subscribe((count) => {
console.log('fromEvent' + count);
});
/// 第一次點擊輸出: fromEvent1;第二次點擊輸出fromEvent2;依次同理
(2). from: 將各種其他對象和數據類型轉化為 Observables
const arrayData = [5, 6];
Observable.from(arrayData).pipe(
scan((scanData, item) => scanData += item, 10),
map((item) => item * 2),
).subscribe((data: any) => {
console.log('from:' + data);
});
/// 瀏覽器輸出 from:30 from:42
(3). of: 創建一個 Observable,它會依次發出由你提供的參數,最后發出完成通知。
Observable.of('value1', 'value2')
.subscribe((data: any) => {
console.log('of:' + data);
});
/// 瀏覽器輸出 of:value1 of: value2
(4). interval: 返回一個無線自增的序列整數
const numbers = Rx.Observable.interval(1000);
numbers.subscribe(x => console.log('interval:'+x));
/// 瀏覽器輸出: interval:1 interval2 依次增加
(5). create: 創建Observable對象, 當觀察者( Observer )訂閱該 Observable 時,它會執行指定的函數
const obs = Observable.create((obsever) => {
obsever.next('add');
obsever.next('upt');
obsever.complete(); // 代表完成,之后的語句將不再會被調用;;;
obsever.next('del');
});
// 訂閱觀察者
obs.map(data => data + 'Map').subscribe((data: any) => {
console.log(data);
});
/// 瀏覽器輸出: addMap uptMap
2-2. 轉換操作符 : Map、MergeMap、MapTo、Scan
(1). Map: 把每個源值傳遞給轉化函數以獲得相應的輸出值
Rx.Observable.from([1, 2])
.map((item) => item * 2)
.subscribe((data: any) => { console.log('map:' + data);});
/// 瀏覽器輸出: map: 2 map: 4
(2). MergeMap: 將每個源值投射成 Observable ,該 Observable 會合並到輸出 Observable 中;;;;可用於串聯請求
const mergeA = Observable.of(1, 2, 3);
const mergeB = mergeA.map(r => Observable.of(r)).mergeMap(r => r);
mergeB.subscribe(c => console.log('mergeMap:' + c));
/// 瀏覽器輸出: mergeMap1 mergeMap2 mergeMap3
(3). MapTo: 類似於 map,但它每一次都把源值映射成同一個輸出值。
Observable.of(1, 2, 3).mapTo(33).subscribe(data => {console.log(data);});
/// 瀏覽器輸出: 3個55
(4). Scan: 對源 Observable 使用累加器函數, 返回生成的中間值, 可選的初始值
Rx.Observable.from([1, 2]).pipe(
scan((acc, item) => acc += item, 10)) // acc為一個新變量,item為[1,2]中的每一項, 10為新變量acc的默認初始值;返回新生成的中間值acc reduce同理
.subscribe(v => console.log(v))
/// 瀏覽器輸出 11 13
2-3. 數學和聚合操作符:reduce
(1). reduce: 和scan同理;只不過中間變量的值不會清0,會保留上一次源操作之后的得到的中間值;並且只會輸出最后一個值;
Rx.Observable.from([1, 2]).pipe(
reduce((acc, item) => acc += item, 10))
.subscribe(v => console.log(v))
// 輸出
13
2-4. 過濾操作符: filter、throttleTime
(1). filter: 數據進行過濾返回你想要的數據
import {Observable} from 'rxjs';
import {filter} from 'rxjs/internal/operators';
from([2, 3, 4]).pipe(
filter(item => item <= 3))
.subscribe(v => console.log(v))
// 瀏覽器輸出: 2 3
(2). throttleTime: 在一定時間范圍內不管產生了多少事件,它只放第一個過去,剩下的都將舍棄
####### 實現: 一秒內不管有多少點擊事件;只觸發一次點擊事件;,
const throttleElem = document.querySelector('#throttleElem');
// 一秒內只觸發一次點擊事件
Rx.Observable.fromEvent(throttleElem, 'click')
.throttleTime(1000)
.scan(count => count + 1, 0)
.subscribe(data => {
console.log('點擊了' + data + '次');
});