How to implement proper switchMap operator in Combine?

switchmap http request
switchmap multiple observables
switchmap vs mergemap
concatmap array of observables
rxjs concatmap
rxjs mergemap
rxjs flatmap
concatmap angular 6

Consider the following example:

    cancellable = Just(2).map { x in
        Just(x * x).delay(for: 2.0, scheduler: RunLoop.main)
    }
    .switchToLatest()
    .sink(receiveCompletion: {_ in
        print("completed")
    }, receiveValue: {result in
        print(result)
    })

Here I try to mimic behavior of famous switchMap operator using Combine operators. I expect to get result after two seconds and completion. In reality neither result nor completion comes. Which is very bad because upstream was completed!

Looks like switchToLatest cancels itself as soon as upstream completes and forgets to complete. On the other hand if I replace it with a flatMap everything works as expected.

Are there any good examples of a proper switchMap operator?

Disclaimer: Well I do understand my upstream completes. Though I want my switchMap to work irrespectively if my upstream completed before inner publisher or after.

Did not you mean for the following (at least, as far as I understood, it results in what seems you expected)?

let cancellable = Just(2)
    .map { x in
        Just(x * x)
    }
    .delay(for: 2.0, scheduler: RunLoop.main)
    .switchToLatest()
    .sink(receiveCompletion: {_ in
        print("completed")
    }, receiveValue: {result in
        print(result)
    })

RxJs SwitchMap Operator Deep Dive : How Does It Work? Learn , And right after the most familiar operators that are also available in arrays To see the selector function use case in action, have a look at this video Let's then try the switchMap operator to combine two HTTP requests, and� The map operator. The map operator is the most common of all. For each value that the Observable emits you can apply a function in which you can modify the data. But unlike switchMap, that

I think that's a bug. Try using flatMap instead, which works as expected.

let cancellable = Just(2)
.flatMap { (x) in
    Just(x * x)
        .delay(for: 2.0, scheduler: RunLoop.main)
}
.sink(receiveCompletion: {_ in
    print("completed")
}, receiveValue: {result in
    print(result)
})

RxJs Mapping: switchMap vs mergeMap vs concatMap vs exhaustMap, Knowing which operator to use in a given situation (and why) can be a bit The RxJs exhaustMap Operator; How to choose the right mapping Operator? Merge, unlike concat, will not wait for an Observable to complete� I ended up achieving this by publishing + replaying the inner observables with publishReplay(1) and then ref counting.. Note that refCount is not sufficient because the count will drop to 0 when switchMap unsubscribes from the previous inner observable (before it subscribes to the new inner observable), so I had to use a special refCountWithDelay operator which only unsubscribes by ref

Indeed, switchToLatest is probably what you're looking for. The problem is that it is buggy. Or at least it was; the bug is fixed in Xcode 11.4 (currently in beta) and now switchToLatest behaves exactly as one would expect. Your code now works correctly:

    Just(2).map { x in
        Just(x * x).delay(for: 2.0, scheduler: RunLoop.main)
    }
    .switchToLatest()
    .sink(receiveCompletion: {_ in
        print("completed")
    }, receiveValue: {result in
        print(result)
    }).store(in:&storage)  // 4, completed

switchMap, This operator is generally considered a safer default to mergeMap ! Why use switchMap ? for instance if you used mergeMap with an interval and forgot to properly dispose of inner import { interval, fromEvent, merge, empty } from 'rxjs'; . Some of the most commonly used RxJs operators that we find on a daily basis are the RxJs higher-order mapping operators: switchMap, mergeMap, concatMap and exhaustMap. For example, most of the network calls in our program are going to be done using one of these operators, so getting familiar with them is essential in order to write almost any

mergeMap, concatMap, switchMap and when to use them, Okay now that the merge operator has been covered lets see how we use the mergeMap operator to make our nested subscribe example� When a new inner Observable is emitted, the switchMap stops emitting items from previous inner Observable and starts emitting items from latest inner Observable. It continues to do in the same way for all subsequent inner Observable. switchMap is a RxJS pipeable operator and it is used within pipe function of Observable from RxJS 6. switchMap

Learn RxJS switchMap, mergeMap, concatMap and exhaustMap , how the other RxJS operators: mergeMap , concatMap and exhaustMap And without even realizing it, we just applied the “merge” strategy. you want to apply, and then choose the appropriate operator for that strategy. So as we can see the switchMap operator is a great way of doing one HTTP request using the output of an initial request here, so this is one common way that we can use it. But at this point, we might have a couple of questions in mind, like for example:

Decouple switching logic from switchMap operator and consistent , Now, note that transform operator can be used to implement the host of basic so this is the correct impl: flatMapLatest(block) = cancelOnNext(). Demote switchMap and combineLatest to preview features as we may want… Merge: combine multiple Observables into one by merging their emissions; SwitchMap: transform the items emitted by an Observable into Observables, and mirror those items emitted by the most-recently transformed Observable; Learn about RxJava Operator - Map Vs FlatMap. FlatMap & Map are very important operators in RxJava.

Comments
  • Yuck seems like another bug in Combine. I've been struggling with a combination of .receive(on: queue).combineLatest(Just(2)). Just goes silent like in your example, and flatMap works just fine.
  • Thanks for asking that question; this just bit me too, so I'm happy to find out I'm not alone.
  • The bug is fixed in Xcode 11.4
  • Sorry, that's not what I meant. I wanted to show that the following example doesn't generate outputs and completed events which is an error by itself. Also in your example you delayed the output of a map while I delayed inner observable of the map which caused the behavior in question.
  • To make it even simpler: I think that publisher.map(transform).switchToLatest() should generate events even if publisher completes before inner publisher.
  • True, except that flatMap is not what I want :-) I want a switchMap actually. Imagine I have a stream instead of Just() and I do want to cancel previous subscriptions when it emits. Well I already implemented a custom operator doing it so probably will post it here later.
  • @norekhov please post your solution, would love to learn from it.
  • @norekhov btw there are really not many docs available to be fair, I follow this unofficial one: heckj.github.io/swiftui-notes/…. Based on what it says there is no difference between .map().switchToLatest() and .flatMap(). Are you coming from ReactiveCocoa perhaps?
  • You can check my solution here: github.com/tcldr/Entwine/issues/16. Maybe it will be included in Entwine or the author will suggest some other workaround. This is actually only switchToLatestWaitable but it can be combined with map to form proper switchMap