【发布时间】:2019-09-12 09:24:59
【问题描述】:
【问题讨论】:
-
Observable<A>.map(A -> B): Observable<B>;Observable<A>.switchMap(A -> Observable<B>): Observable<B>
【问题讨论】:
Observable<A>.map(A -> B): Observable<B>; Observable<A>.switchMap(A -> Observable<B>): Observable<B>
两个运算符不同。
switchMap:将值映射到 observable。取消之前的内部 observable。
fromEvent(document, 'click')
.pipe(
// restart counter on every click
// First click: 0, 1, 2...
// Second click: cancels the previous interval and starts new one. 0, 1, 2...
switchMap(() => interval(1000))
)
.subscribe(console.log);
map:为每个值添加投影。
//add 10 to each value
const example = source.pipe(map(val => val + 10));
【讨论】:
在某些情况下它根本没有影响吗?
没有。他们是两种完全不同的野兽。 switchMap 应该返回一个 observable,map 可以返回任何东西。他们的应用是不同的。它通常是这样的:
someStream$.pipe(
switchMap(args => makeApiCall(args)), // must return a stream
map(response => process(response)) // returns a value of any shape, usually an object or a primitive
).subscribe(doSomethingWithResults);
还有其他与switchMap本质上相似的运算符:mergeMap(AKA flatMap)、exhaustMap、concatMap(在某些情况下,所有这些都或多或少是相同的东西),但不是map。
【讨论】:
Map - 它的作用类似于数组中的映射。 map 接收从 Observable 发出的每个值,对其执行操作。
var observable = Rx.Observable.interval(1000);
var observer = {
next: function(value) {
console.log(value);
}
};
observable.map(function(value) {
return value*10;
}).subscribe(observer);
SwitchMap - switchMap 将订阅外部 Observable 内的所有内部 Observable,但不会合并内部 Observable。而是切换到最新的 Observable 并将其传递给链。
假设顶部的每条橙色垂直线代表 1 秒。这意味着外部 Observable (OO) 在 1、4 和 5.5 秒发出值,而内部 Observable (IO) 在 3 秒内每秒发出值,从订阅后立即开始(时间为零)。
前三个输出值(10、10、10)看起来很简单。只需根据运算符逻辑为它们中的每一个乘以 1 x 10 = 10。基于这前三个值,我们可以说对于每个 OO 值,IO 都会发出它的所有值。
这个假设似乎适用于第一个输出值 30……和第二个输出值 30……
但它不应该发出 30 的最终值吗?
这就是 switchMap 逻辑的用武之地。每次 OO 发出一个值时,IO 都会发出它的所有值,除非 OO 在 IO 完成发出它的所有值之前发出一个新值。当 OO 发出一个值 5 并且我们的最后一个值 30 似乎被“取消”时,我们可以看到这一点。
将每个源值投影到一个 Observable 中,该 Observable 合并到输出 Observable 中,仅从最近投影的 Observable 发出值。
var button = document.querySelector('button');
var obs1 = Rx.Observable.fromEvent(button, 'click');
var obs2 = Rx.Observable.interval(1000);
obs1.switchMap(
event => {
return obs2
}
).subscribe(
(value) => console.log(value)
);
在上面的例子中,无论我点击多少次按钮,我总是会得到从 0 开始的值,因为switchMap 切换到最新的 observable。
最好的用例是我们想要根据从外部 observable 接收到的数据进行 API 调用。
阅读更多 -
https://zach-gollwitzer.medium.com/how-to-read-an-rxjs-marble-diagram-f6e8dfa29781 https://dev.to/bhagatparwinder/map-vs-mergemap-vs-switchmap-5gee https://blogs.msmvps.com/deborahk/higher-order-observable/
【讨论】:
查看 2 个函数的定义:
map<inputType, outputType>(syncFunction: (input: inputType) => outputType )
switchmap<inputType, Observable<outputType>>( asyncFunction: (input: inputType) => Observable<outputType> )
map = 一个异步函数调用一个同步函数(asyncTask => syncTask)
switchMap = 一个异步函数顺序调用一个异步函数(asyncTask => asyncTask )
switchMap 示例:
observable1 calls observable2 means:
observable1_event1 => new observable2 asynchronous => Task1
observable1_event2 => new observable2 asynchronous => Task2
observable1_event3 ...
如果在 task1 未完成时发出 observable1_event2,则 task1 的 Observable2 将通过调用 unsubscribe() 被拒绝。这意味着Task1之后将不再显示输出。
如果在 task1 完成时发出 observable1_event2。 Task1 的所有输出将正常显示,然后 task2 的输出将显示。
注意:每个新的 observable2 都可以触发很多事件(observable2_event1、observable2_event2、...)
【讨论】: