乐趣区

关于javascript:5-张弹珠图彻底弄清-RxJS-的拉平策略mergeMapswitchMapconcatMapexhaustMap

RxJS 的操作符了解起来的确比较复杂,比方最罕用的几种 map 操作符,本篇就来使劲冲一冲它们!!

  • 原创文章,非商业转载请说名出处

map 操作想必大家肯定不生疏:

const {of} = Rx;
const {map} = RxOperators;

const namesObservable = of('A', 'B');
namesObservable.pipe(map(name => `map ${name}`)
)

namesObservable .subscribe(result => console.log(`${result}`))

// map A
// map B

很直观,因为 map 映射的是“值”,所以足够简略~

然而,如果说,map 映射的是 observable 呢?

const {of} = Rx;
const {map} = RxOperators;

const namesObservable = of('A', 'B');

const http =(name)=>{return of(`${name} 1`,`${name} 2`);
}

namesObservable.pipe(map(name => http(name))
)

namesObservable.subscribe(result => console.log(`${result}`))

// 则会失去两个 observable 对象
// ****observable{..}
// observable{..}

咱们在 [](https://rxviz.com/)https://rxviz.com/ 的弹珠图中,能够清晰的看到:返回的仍是 observable

并且 observable 由最后的 1 个,变成了 2 个(圆圈就是 observable),数据仍在外面没有被订阅解析进去。

尽管,咱们能够用 粗犷 的办法,在订阅 .subscribe 外面再次调用订阅 .subscribe,则可得值:

const {of} = Rx;
const {map} = RxOperators;

const namesObservable = of('A', 'B');

const http =(name)=>{return of(`${name} 1`,`${name} 2`);
}

namesObservable.pipe(map(name => http(name))
)

namesObservable .subscribe(resultObservable => {resultObservable.subscribe(result => console.log(`${result}`) )
})

// A1
// A2
// B1
// B2

然而,这样包裹写法注定是不优雅的,所以,为了解决这个差别,RxJS 引入了 —— Flattening(扁平化)策略!!

咱们能够借助 flatMap 操作符,则能失去同样的解析值的成果~

flatMap 其实也就是咱们熟知的 mergeMap 操作符;

代码如下:

const {of} = Rx;
const {mergeMap} = RxOperators;

const namesObservable = of('A', 'B');

const http =(name)=>{return of(`${name} 1`,`${name} 2`);
}

namesObservable.pipe(mergeMap(name => http(name))
)

namesObservable.subscribe(result => console.log(`${result}`))
// A1
// A2
// B1
// B2

更进一步,沿着这种偏平化策略的思路,除了 mergeMap,RxJS 又引入了 switchMap、concatMap 和 exhaustMap,它们可能提供不同方向的拉平策略。

咱们再借助 [](https://rxviz.com/)https://rxviz.com/ 的弹珠图,一眼便能看到它们的差别:

设置一个定时器,每一秒都收回一个 observable,一共发 3 次,来看下别离得值;

  • mergeMap
const {of,interval} = Rx;
const {mergeMap,take,map} = RxOperators;

const namesObservable = of('A', 'B');

const http =(name)=>{return interval(1000)
      .pipe(take(3),
        map(()=>of(`${name} 1`,`${name} 2`))
      )
}

namesObservable.pipe(mergeMap(name => http(name))
)

mergeMap 会同时保护多个流动的外部订阅;

  • switchMap
const {of,interval} = Rx;
const {switchMap,take,map} = RxOperators;

const namesObservable = of('A', 'B');

const http =(name)=>{return interval(1000)
      .pipe(take(3),
        map(()=>of(`${name} 1`,`${name} 2`))
      )
}

namesObservable.pipe(switchMap(name => http(name))
)

switchMap,在每次收回时,会勾销前一个外部 observable 的订阅,而后订阅一个新的 observable;

  • concatMap
const {of,interval} = Rx;
const {concatMap ,take,map} = RxOperators;

const namesObservable = of('A', 'B');

const http =(name)=>{return interval(1000)
      .pipe(take(3),
        map(()=>of(`${name} 1`,`${name} 2`))
      )
}

namesObservable.pipe(concatMap (name => http(name))
)

concatMap 会在之前前一个外部 observable 实现后,才会订阅下一个;

  • exhaustMap
const {of,interval} = Rx;
const {exhaustMap ,take,map} = RxOperators;

const namesObservable = of('A', 'B');

const http =(name)=>{return interval(1000)
      .pipe(take(3),
        map(()=>of(`${name} 1`,`${name} 2`))
      )
}

namesObservable.pipe(exhaustMap (name => http(name))
)

exhaustMap 映射成外部 observable,疏忽其余值直到该 observable 实现;


OK,以上便是本篇分享。

感觉不错点个赞吧👍👍👍,您的激励,我的能源,保持输入品质好文~~ 欢送评论探讨

我是掘金安东尼,输入裸露输出,技术洞见生存。再会吧~~ 👋👋👋

退出移动版