通过一个案例来理解回调地狱,通过 http 请求获取人、行星和星系,先找到人,然后是行星,最后是星系。这涉及三个异步操作的回调。如下每个回调内部依赖于其父级,这会导致回调地狱的’厄运金字塔’风格。

    1. getPerson(person => {
    2. getPlanet(person, (planet) => {
    3. getGalaxy(planet, (galaxy) => {
    4. console.log(galaxy)
    5. })
    6. })
    7. })

    在 RxJS 中通过 mergeMap 解决这个问题

    1. getPerson()
    2. .mergeMap(person => getPlanet(person))
    3. .mergeMap(planet => getGalaxy(planet))
    4. .subscribe(galaxy => console.log(galaxy))

    如上,代码被扁平化并包含单个方法调用链,没有回调地狱的问题。
    Promise 也是避免回调地狱的一种方式,其特点是无论有没有人关心它的执行结果,它都会立即开始执行,并且你没有机会取消这次执行。
    相比 Promise ,Observable 可观察对象,能够在它变化时通知观察者。(Observable 负责生产数据,观察者负责消费数据)


    基本概念:
    可观察对象:Observable、Subject、BehaviorSubject、ReplaySubject

    • ReplaySubject:新的订阅者会广播所有历史结果
    • BehaviorSubject:创建 Observable 对象时可以传默认值,观察者订阅后会直接拿到默认值

    数据流:从可观察对象内部输出的数据就是数据流
    操作符:操作数据流,进行转换/过滤
    辅助方法:返回 Observable 对象,可进行订阅
    可观察对象的特性:

    • Observable 对象内部可多次调用 next 方法
    • Observable 对象内部调用 complete 方法终止
    • Observable 内部逻辑错误,通过 error 方法发送给订阅者 observer.error(err)
    • 可观察对象是惰性的,订阅后才会执行
    • 可观察对象可以有 n 多订阅者

    RxJS 操作符
    辅助方法:from(args) 参数可以是数组/promise对象,生成 Observable 对象
    forkJoin:类似 Promise.all 即所有 Observable 完成后才一次性返回值

    1. forkJoin({
    2. goods: from(axios.get(...)),
    3. category: ...,
    4. }).subscribe(console.log)

    switchMap:切换可观察对象
    点击事件:事件是一个可观察对象

    1. fromEvent(button, 'click').pipe(
    2. switchMap(event => interval(1000))
    3. ).subscribe(console.log)

    take(2):获取数据流中的前几个
    takeUntil:接收可观察对象,当可观察对象发出值时终止数据源

    1. fromEvent(document, 'mouse').pipe(takeUntil(fromEvent(button, 'click')).subscribe()

    combineLatest:任意 Observable 发出值时,发出每个 Observable 的最新值。多个 Observable 依靠彼此进行计算。
    startWith:发出给定的第一个值

    1. const source = of(1,2,3)
    2. const example = source.pipe(startWith(0))
    3. example.subscribe()

    错误处理:catchError:返回一个 Observable 对象