RxJS官網(wǎng)
1 概述
1.1 什么是 RxJS
?
RxJS
是一個(gè)用于處理異步編程的 JavaScript
庫骂际,目標(biāo)是使編寫異步和基于回調(diào)的代碼更容易
1.2 為什么要學(xué)習(xí) RxJS
?
就像 Angular
深度集成 TypeScript
一樣查近,Angular
也深度集成了 RxJS
服務(wù)伟恶、表單阀捅、事件娩嚼、全局狀態(tài)管理体捏、異步請(qǐng)求 ...
1.3 快速入門
可觀察對(duì)象 (
Observable
) :類比Promise
對(duì)象染苛,內(nèi)部可以用于執(zhí)行異步代碼,通過調(diào)用內(nèi)部提供的方法將異步代碼執(zhí)行的結(jié)果傳遞到可觀察對(duì)象外部觀察者 (
Observer
):類比then
方法中的回調(diào)函數(shù)毁兆,用于接收可觀察對(duì)象中傳遞出來數(shù)據(jù)-
訂閱 (
subscribe
):類比then
方法浙滤,通過訂閱將可觀察對(duì)象和觀察者連接起來,當(dāng)可觀察對(duì)象發(fā)出數(shù)據(jù)時(shí)气堕,訂閱者可以接收到數(shù)據(jù)纺腊。import { Observable } from "rxjs" const observable = new Observable(function (observer) { setTimeout(function () { observer.next({ name: "張三" }) }, 2000) }) const observer = { next: function (value) { console.log(value) } } observable.subscribe(observer)
2. 可觀察對(duì)象
2.1 Observable
-
在
Observable
對(duì)象內(nèi)部可以多次調(diào)用next
方法向外發(fā)送數(shù)據(jù)const observable = new Observable(function (observer) { let index = 0 setInterval(function () { observer.next(index++) }, 1000) }) const observer = { next: function (value) { console.log(value) } } observable.subscribe(observer)
-
當(dāng)所有數(shù)據(jù)發(fā)送完成以后,可以調(diào)用
complete
方法終止數(shù)據(jù)發(fā)送const observable = new Observable(function (observer) { let index = 0 let timer = setInterval(function () { observer.next(index++) if (index === 3) { observer.complete() clearInterval(timer) } }, 1000) }) const observer = { next: function (value) { console.log(value) }, complete: function () { console.log("數(shù)據(jù)發(fā)送完成") } } observable.subscribe(observer)
-
當(dāng)
Observable
內(nèi)部邏輯發(fā)生錯(cuò)誤時(shí)茎芭,可以調(diào)用error
方法將失敗信息發(fā)送給訂閱者揖膜,Observable
終止import { Observable } from "rxjs" const observable = new Observable(function (observer) { let index = 0 let timer = setInterval(function () { observer.next(index++) if (index === 3) { observer.error("發(fā)生錯(cuò)誤") clearInterval(timer) } }, 1000) }) const observer = { next: function (value) { console.log(value) }, error: function (error) { console.log(error) } } observable.subscribe(observer)
-
可觀察對(duì)象是惰性的,只有被訂閱后才會(huì)執(zhí)行
const observable = new Observable(function () { console.log("Hello RxJS") }) // observable.subscribe()
-
可觀察對(duì)象可以有
n
多訂閱者梅桩,每次被訂閱時(shí)都會(huì)得到執(zhí)行const observable = new Observable(function () { console.log("Hello RxJS") }) observable.subscribe() observable.subscribe() observable.subscribe() observable.subscribe() observable.subscribe()
-
取消訂閱
import { interval } from "rxjs" const obs = interval(1000) const subscription = obs.subscribe(console.log) setTimeout(function () { subscription.unsubscribe() }, 2000)
2.2 Subject
-
用于創(chuàng)建空的可觀察對(duì)象壹粟,在訂閱后不會(huì)立即執(zhí)行,
next
方法可以在可觀察對(duì)象外部調(diào)用import { Subject } from "rxjs" const demoSubject = new Subject() demoSubject.subscribe({next: function (value) {console.log(value)}}) demoSubject.subscribe({next: function (value) {console.log(value)}}) setTimeout(function () { demoSubject.next("hahaha") }, 3000)
2.3 BehaviorSubject
擁有 Subject
全部功能宿百,但是在創(chuàng)建 Obervable
對(duì)象時(shí)可以傳入默認(rèn)值趁仙,觀察者訂閱后可以直接拿到默認(rèn)值
import { BehaviorSubject } from "rxjs"
const demoBehavior = new BehaviorSubject("默認(rèn)值")
demoBehavior.subscribe({next: function (value) {console.log(value)}})
demoBehavior.next("Hello")
2.4 ReplaySubject
功能類似 Subject
,但有新訂閱者時(shí)兩者處理方式不同垦页,Subject
不會(huì)廣播歷史結(jié)果雀费,而 ReplaySubject
會(huì)廣播所有歷史結(jié)果
import { ReplaySubject } from "rxjs"
const rSubject = new ReplaySubject()
rSubject.subscribe(value => {
console.log(value)
})
rSubject.next("Hello 1")
rSubject.next("Hello 2")
setTimeout(function () {
rSubject.subscribe({next: function (value) {console.log(value)}})
}, 3000)
3. 輔助方法
3.1 range
range(start, length)
,調(diào)用方法后返回 observable
對(duì)象外臂,被訂閱后會(huì)發(fā)出指定范圍的數(shù)值
import { range } from "rxjs"
range(0, 5).subscribe(n => console.log(n))
// 0
// 1
// 2
// 3
// 4
方法內(nèi)部并不是一次發(fā)出 length
個(gè)數(shù)值坐儿,而是發(fā)送了 length
次,每次發(fā)送一個(gè)數(shù)值宋光,就是說內(nèi)部調(diào)用了 length
次 next
方法
3.2 of
將參數(shù)列表作為數(shù)據(jù)流返回
of("a", "b", [], {}, true, 20).subscribe(v => console.log(v))
3.3 from
將 Array
貌矿、Promise
、Iterator
轉(zhuǎn)換為 observable
對(duì)象
from(["a", "b", "c"]).subscribe(v => console.log(v))
// a
// b
// c
import { from } from "rxjs"
function p() {
return new Promise(function (resolve) {
resolve([100, 200])
})
}
from(p()).subscribe(v => console.log(v))
// [100, 200]
3.4 interval
罪佳、timer
Interval:每隔一段時(shí)間發(fā)出一個(gè)數(shù)值逛漫,數(shù)值遞增
import { interval } from "rxjs"
interval(1000).subscribe(n => console.log(n))
timer:間隔時(shí)間過去以后發(fā)出數(shù)值,行為終止赘艳,或間隔時(shí)間發(fā)出數(shù)值后酌毡,繼續(xù)按第二個(gè)參數(shù)的時(shí)間間隔繼續(xù)發(fā)出值
import { timer } from "rxjs"
timer(2000).subscribe(n => console.log(n))
timer(0, 1000).subscribe(n => console.log(n))
3.5 concat
合并數(shù)據(jù)流克握,先讓第一個(gè)數(shù)據(jù)流發(fā)出值,結(jié)束后再讓第二個(gè)數(shù)據(jù)流發(fā)出值枷踏,進(jìn)行整體合并
import { concat, range } from "rxjs"
concat(range(1, 5), range(6, 5)).subscribe(console.log)
3.6 merge
合并數(shù)據(jù)流菩暗,多個(gè)參數(shù)一起發(fā)出數(shù)據(jù)流,按照時(shí)間線進(jìn)行交叉合并
import { merge, fromEvent, interval } from "rxjs"
const clicks = fromEvent(document, "click")
const timer = interval(1000)
merge(clicks, timer).subscribe(console.log)
3.7 combineLatest
將兩個(gè) Obserable
中最新發(fā)出的數(shù)據(jù)流進(jìn)行組合成新的數(shù)據(jù)流旭蠕,以數(shù)組的形式發(fā)出停团。和當(dāng)前最新的進(jìn)行組合
import { combineLatest, timer } from "rxjs"
const firstTimer = timer(0, 1000) // emit 0, 1, 2... after every second, starting from now
const secondTimer = timer(500, 1000) // emit 0, 1, 2... after every second, starting 0,5s from now
combineLatest(firstTimer, secondTimer).subscribe(console.log)
// [0, 0] after 0.5s
// [1, 0] after 1s
// [1, 1] after 1.5s
// [2, 1] after 2s
3.8 zip
將多個(gè) Observable
中的數(shù)據(jù)流進(jìn)行組合。和將來最新的進(jìn)行組合
import { zip, of } from "rxjs"
import { map } from "rxjs/operators"
let age = of(27, 25, 29)
let name = of("Foo", "Bar", "Beer")
let isDev = of(true, true, false)
zip(name, age, isDev)
.pipe(map(([name, age, isDev]) => ({ name, age, isDev })))
.subscribe(console.log)
// { name: 'Foo', age: 27, isDev: true }
// { name: 'Bar', age: 25, isDev: true }
// { name: 'Beer', age: 29, isDev: false }
3.9 forkJoin
forkJoin
是 Rx
版本的 Promise.all()
掏熬,即表示等到所有的 Observable
都完成后佑稠,才一次性返回值
import axios from "axios"
import { forkJoin, from } from "rxjs"
axios.interceptors.response.use(response => response.data)
forkJoin({
goods: from(axios.get("http://localhost:3005/goods")),
category: from(axios.get("http://localhost:3005/category"))
}).subscribe(console.log)
3.10 throwError
返回可觀察對(duì)象并向訂閱者拋出錯(cuò)誤
import { throwError } from "rxjs"
throwError("發(fā)生了未知錯(cuò)誤").subscribe({ error: console.log })
3.11 retry
如果 Observable
對(duì)象拋出錯(cuò)誤,則該輔助方法會(huì)重新訂閱 Observable
以獲取數(shù)據(jù)流旗芬,參數(shù)為重新訂閱次數(shù)
import { interval, of, throwError } from "rxjs"
import { mergeMap, retry } from "rxjs/operators"
interval(1000)
.pipe(
mergeMap(val => {
if (val > 2) {
return throwError("Error!")
}
return of(val)
}),
retry(2)
)
.subscribe({
next: console.log,
error: console.log
})
3.12 race
接收并同時(shí)執(zhí)行多個(gè)可觀察對(duì)象舌胶,只將最快發(fā)出的數(shù)據(jù)流傳遞給訂閱者
import { race, timer } from "rxjs"
import { mapTo } from "rxjs/operators"
const obs1 = timer(1000).pipe(mapTo("fast one"))
const obs2 = timer(3000).pipe(mapTo("medium one"))
const obs3 = timer(5000).pipe(mapTo("slow one"))
race(obs3, obs1, obs2).subscribe(console.log)
3.13 fromEvent
將事件轉(zhuǎn)換為 Observable
import { fromEvent } from "rxjs"
const btn = document.getElementById("btn")
// 可以將 Observer 簡(jiǎn)寫成一個(gè)函數(shù),表示 next
fromEvent(btn, "click").subscribe(e => console.log(e))
4. 操作符
- 數(shù)據(jù)流:從可觀察對(duì)象內(nèi)部輸出的數(shù)據(jù)就是數(shù)據(jù)流疮丛,可觀察對(duì)象內(nèi)部可以向外部源源不斷的輸出數(shù)據(jù)
- 操作符:用于操作數(shù)據(jù)流幔嫂,可以對(duì)象數(shù)據(jù)流進(jìn)行轉(zhuǎn)換,過濾等操作
4.1 map
这刷、mapTo
map:對(duì)數(shù)據(jù)流進(jìn)行轉(zhuǎn)換婉烟,基于原有值進(jìn)行轉(zhuǎn)換
import { interval } from "rxjs"
import { map } from "rxjs/operators"
interval(1000)
.pipe(map(n => n * 2))
.subscribe(n => console.log(n))
mapTo:對(duì)數(shù)據(jù)流進(jìn)行轉(zhuǎn)換,不關(guān)心原有值暇屋,可以直接傳入要轉(zhuǎn)換后的值
import { interval } from "rxjs"
import { mapTo } from "rxjs/operators"
interval(1000)
.pipe(mapTo({ msg: "接收到了數(shù)據(jù)流" }))
.subscribe(msg => console.log(msg))
4.2 filter
對(duì)數(shù)據(jù)流進(jìn)行過濾
import { range } from "rxjs"
import { filter } from "rxjs/operators"
range(1, 10)
.pipe(filter(n => n % 2 === 0))
.subscribe(even => console.log(even))
4.3 pluck
獲取數(shù)據(jù)流對(duì)象中的屬性值
import { interval } from "rxjs"
import { pluck, mapTo } from "rxjs/operators"
interval(1000)
.pipe(
mapTo({ name: "張三", a: { b: "c" } }),
pluck("a", "b")
)
.subscribe(n => console.log(n))
4.4 first
獲取數(shù)據(jù)流中的第一個(gè)值或者查找數(shù)據(jù)流中第一個(gè)符合條件的值,類似數(shù)組中的 find
方法洞辣。獲取到值以后終止行為
import { interval } from "rxjs"
import { first } from "rxjs/operators"
interval(1000)
.pipe(first())
.subscribe(n => console.log(n))
interval(1000)
.pipe(first(n => n === 3))
.subscribe(n => console.log(n))
4.5 startWith
創(chuàng)建一個(gè)新的 observable
對(duì)象并將參數(shù)值發(fā)送出去咐刨,然后再發(fā)送源 observable
對(duì)象發(fā)出的值
在異步編程中提供默認(rèn)值的時(shí)候非常有用
import { interval } from "rxjs"
import { map, startWith } from "rxjs/operators"
interval(1000)
.pipe(
map(n => n + 100),
startWith(505)
)
.subscribe(n => console.log(n))
// 505
// 100
// 101
// 102
// ...
4.6 every
查看數(shù)據(jù)流中的每個(gè)值是否都符合條件,返回布爾值扬霜。類似數(shù)組中的 every
方法
import { range } from "rxjs"
import { every, map } from "rxjs/operators"
range(1, 9)
.pipe(
map(n => n * 2),
every(n => n % 2 === 0)
)
.subscribe(b => console.log(b))
4.7 delay
定鸟、delayWhen
delay:對(duì)上一環(huán)節(jié)的操作整體進(jìn)行延遲,只執(zhí)行一次
import { from } from "rxjs"
import { delay, map, tap } from "rxjs/operators"
from([1, 2, 3])
.pipe(
delay(1000),
tap(n => console.log("已經(jīng)延遲 1s", n)),
map(n => n * 2),
delay(1000),
tap(() => console.log("又延遲了 1s"))
)
.subscribe(console.log)
// tap 操作符不會(huì)對(duì)數(shù)據(jù)流造成影響, 它被用來執(zhí)行簡(jiǎn)單的副作用, 比如輸出, 但是復(fù)雜的副作用不要在這執(zhí)行, 比如 Ajax
delayWhen:對(duì)上一環(huán)節(jié)的操作進(jìn)行延遲著瓶,上一環(huán)節(jié)發(fā)出多少數(shù)據(jù)流联予,傳入的回調(diào)函數(shù)就會(huì)執(zhí)行多次
import { range, timer } from "rxjs"
import { delayWhen } from "rxjs/operators"
range(1, 10)
.pipe(
delayWhen(n => {
console.log(n)
return timer(n * 1000)
})
)
.subscribe(console.log)
4.8 take
、takeWhile
材原、takeUtil
take:獲取數(shù)據(jù)流中的前幾個(gè)
import { range } from "rxjs"
import { take } from "rxjs/operators"
range(1, 10).pipe(take(5)).subscribe(console.log)
takeWhile:根據(jù)條件從數(shù)據(jù)源前面開始獲取
import { range } from "rxjs"
import { takeWhile } from "rxjs/operators"
range(1, 10)
.pipe(takeWhile(n => n < 8))
.subscribe(console.log)
takeUntil:接收可觀察對(duì)象沸久,當(dāng)可觀察對(duì)象發(fā)出值時(shí),終止主數(shù)據(jù)源
import { interval, timer } from "rxjs"
import { takeUntil } from "rxjs/operators"
interval(100)
.pipe(takeUntil(timer(2000)))
.subscribe(console.log)
// 結(jié)果少兩個(gè)數(shù)據(jù)流的原因:第一次和最后一次余蟹,都需要延遲 100 毫秒卷胯。
4.9 skip
、skipWhile
威酒、skipUntil
skip:跳過前幾個(gè)數(shù)據(jù)流
import { range } from "rxjs"
import { skip } from "rxjs/operators"
range(1, 10).pipe(skip(5)).subscribe(console.log)
skipWhile:根據(jù)條件進(jìn)行數(shù)據(jù)流的跳過
import { range } from "rxjs"
import { skipWhile } from "rxjs/operators"
range(1, 10)
.pipe(skipWhile(n => n < 5))
.subscribe(console.log)
skipUntil:跳過數(shù)據(jù)源中前多少時(shí)間發(fā)出的數(shù)據(jù)流窑睁,發(fā)送從這個(gè)時(shí)間以后數(shù)據(jù)源中發(fā)送的數(shù)據(jù)流
import { timer, interval } from "rxjs"
import { skipUntil } from "rxjs/operators"
interval(100)
.pipe(skipUntil(timer(2000)))
.subscribe(console.log)
4.10 last
獲取數(shù)據(jù)流中的最后一個(gè)
import { range } from "rxjs"
import { last } from "rxjs/operators"
range(1, 10).pipe(last()).subscribe(console.log)
如果數(shù)據(jù)源不變成完成狀態(tài)挺峡,則沒有最后一個(gè)
import { interval } from "rxjs"
import { last, take } from "rxjs/operators"
interval(1000).pipe(take(5), last()).subscribe(console.log)
4.11 concatAll
、concatMap
concatAll:有時(shí) Observable
發(fā)出的又是一個(gè) Obervable
担钮,concatAll
的作用就是將新的可觀察對(duì)象和數(shù)據(jù)源進(jìn)行合并
import { fromEvent, interval } from "rxjs"
import { map, take, concatAll } from "rxjs/operators"
fromEvent(document, "click")
.pipe(
map(event => interval(1000).pipe(take(2))),
concatAll()
)
.subscribe(console.log)
import { map, concatAll } from "rxjs/operators"
import { of, interval } from "rxjs"
interval(1000)
.pipe(
map(val => of(val + 10)),
concatAll()
)
.subscribe(console.log)
concatMap:合并可觀察對(duì)象并處理其發(fā)出的數(shù)據(jù)流
4.12 reduce
橱赠、scan
reduce:類似 JavaScript
數(shù)組中的 reduce
,對(duì)數(shù)數(shù)據(jù)進(jìn)行累計(jì)操作箫津。reduce
會(huì)等待數(shù)據(jù)源中的數(shù)據(jù)流發(fā)送完成后再執(zhí)行病线,執(zhí)行時(shí) reduce
內(nèi)部遍歷每一個(gè)數(shù)據(jù)流進(jìn)行累計(jì)操作,操作完成得到結(jié)果將結(jié)果作為數(shù)據(jù)流發(fā)出
import { interval } from "rxjs"
import { take, reduce } from "rxjs/operators"
interval(500)
.pipe(
take(5),
reduce((acc, value) => acc += value, 0)
)
.subscribe(v => console.log())
scan:類似 reduce
鲤嫡,進(jìn)行累計(jì)操作送挑,但執(zhí)行時(shí)機(jī)不同,數(shù)據(jù)源每次發(fā)出數(shù)據(jù)流 scan
都會(huì)執(zhí)行暖眼。reduce
是發(fā)送出最終計(jì)算的結(jié)果惕耕,而 scan
是發(fā)出每次計(jì)算的結(jié)果
import { interval } from "rxjs"
import { take, scan } from "rxjs/operators"
interval(500)
.pipe(
take(5),
scan((acc, value) => acc += value, 0)
)
.subscribe(v => console.log())
4.13 mergeAll
、mergeMap
mergeAll:交叉合并可觀察對(duì)象
import { fromEvent, interval } from "rxjs"
import { map, mergeAll } from "rxjs/operators"
fromEvent(document, "click")
.pipe(
map(() => interval(1000)),
mergeAll()
)
.subscribe(console.log)
mergeMap:交叉合并可觀察對(duì)象以后對(duì)可觀察對(duì)象發(fā)出的數(shù)據(jù)流進(jìn)行轉(zhuǎn)換
import { of, interval } from "rxjs"
import { mergeMap, map } from "rxjs/operators"
of("a", "b", "c")
.pipe(mergeMap(x => interval(1000).pipe(map(i => x + i))))
.subscribe(x => console.log(x))
4.14 throttleTime
節(jié)流诫肠,可觀察對(duì)象高頻次向外部發(fā)出數(shù)據(jù)流司澎,通過 throttleTime
限制在規(guī)定時(shí)間內(nèi)每次只向訂閱者傳遞一次數(shù)據(jù)流
import { fromEvent } from "rxjs"
import { throttleTime } from "rxjs/operators"
fromEvent(document, "click")
.pipe(throttleTime(2000))
.subscribe(x => console.log(x))
4.15 debounceTime
防抖,觸發(fā)高頻事件栋豫,只響應(yīng)最后一次
import { fromEvent } from "rxjs"
import { debounceTime } from "rxjs/operators"
fromEvent(document, "click")
.pipe(debounceTime(1000))
.subscribe(x => console.log(x))
4.16 distinctUntilChanged
檢測(cè)數(shù)據(jù)源當(dāng)前發(fā)出的數(shù)據(jù)流是否和上次發(fā)出的相同挤安,如相同,跳過丧鸯,不相同蛤铜,發(fā)出
import { of } from "rxjs"
import { distinctUntilChanged } from "rxjs/operators"
of(1, 1, 2, 2, 2, 1, 1, 2, 3, 3, 4)
.pipe(distinctUntilChanged())
.subscribe(x => console.log(x)) // 1, 2, 1, 2, 3, 4
4.17 groupBy
對(duì)數(shù)據(jù)流進(jìn)行分組
import { of } from "rxjs"
import { mergeMap, groupBy, toArray } from "rxjs/operators"
of(
{ name: "Sue", age: 25 },
{ name: "Joe", age: 30 },
{ name: "Frank", age: 25 },
{ name: "Sarah", age: 35 }
)
.pipe(
groupBy(person => person.age),
mergeMap(group => group.pipe(toArray()))
)
.subscribe(console.log)
// [{name: "Sue", age: 25}, { name: "Frank", age: 25 }]
// [{ name: "Joe", age: 30 }]
// [{ name: "Sarah", age: 35 }]
4.18 withLatestFrom
主數(shù)據(jù)源發(fā)出的數(shù)據(jù)流總是和支數(shù)據(jù)源中的最新數(shù)據(jù)流進(jìn)行結(jié)合,返回?cái)?shù)組
import { fromEvent, interval } from "rxjs"
import { withLatestFrom } from "rxjs/operators"
const clicks = fromEvent(document, "click")
const timer = interval(1000)
clicks.pipe(withLatestFrom(timer)).subscribe(console.log)
4.19 switchMap
切換可觀察對(duì)象
import { fromEvent, interval } from "rxjs"
import { switchMap } from "rxjs/operators"
fromEvent(document, "click")
.pipe(switchMap(ev => interval(1000)))
.subscribe(x => console.log(x))
5. 練習(xí)
5.1 元素拖拽
<style>
#box {
width: 200px;
height: 200px;
background: skyblue;
position: absolute;
left: 0;
top: 0;
}
</style>
<div id="box"></div>
// 原生 JavaScript
box.onmousedown = function (event) {
let distanceX = event.clientX - event.target.offsetLeft
let distanceY = event.clientY - event.target.offsetTop
document.onmousemove = function (event) {
let positionX = event.clientX - distanceX
let positionY = event.clientY - distanceY
box.style.left = positionX + "px"
box.style.top = positionY + "px"
}
box.onmouseup = function () {
document.onmousemove = null
}
}
// RxJS
import { fromEvent } from "rxjs"
import { map, switchMap, takeUntil } from "rxjs/operators"
const box = document.getElementById("box")
fromEvent(box, "mousedown")
.pipe(
map(event => ({
distanceX: event.clientX - event.target.offsetLeft,
distanceY: event.clientY - event.target.offsetTop
})),
switchMap(({ distanceX, distanceY }) =>
fromEvent(document, "mousemove").pipe(
map(event => ({
positionX: event.clientX - distanceX,
positionY: event.clientY - distanceY
})),
takeUntil(fromEvent(document, "mouseup"))
)
)
)
.subscribe(({ positionX, positionY }) => {
box.style.left = positionX + "px"
box.style.top = positionY + "px"
})
5.2 搜索
<input id="search" type="text" placeholder="請(qǐng)輸入搜索內(nèi)容..." />
import { fromEvent, from, throwError } from "rxjs"
import { debounceTime, distinctUntilChanged, map, switchMap, catchError } from "rxjs/operators"
import axios from "axios"
const search = document.getElementById("search")
fromEvent(search, "keyup")
.pipe(
debounceTime(700),
map(event => event.target.value),
distinctUntilChanged(),
switchMap(keyword =>
from(
axios.get(`https://j1sonplaceholder.typicode.com/posts?q=${keyword}`)
).pipe(
map(response => response.data),
catchError(error => throwError(`發(fā)生了錯(cuò)誤: ${error.message}`))
)
)
)
.subscribe({
next: value => {
console.log(value)
},
error: error => {
console.log(error)
}
})
5.3 串聯(lián)請(qǐng)求
先獲取token
丛肢,再根據(jù)token
獲取用戶信息
<button id="btn">獲取用戶信息</button>
import axios from "axios"
import { from, fromEvent } from "rxjs"
import { pluck, concatMap } from "rxjs/operators"
const button = document.getElementById("btn")
fromEvent(button, "click")
.pipe(
concatMap(event =>
from(axios.get("http://localhost:3005/token")).pipe(
pluck("data", "token")
)
),
concatMap(token =>
from(axios.get("http://localhost:3005/userInfo")).pipe(
pluck("data")
)
)
)
.subscribe(console.log)