0

switchMap not working with string observable. If I use it inside a function then call the function, it won't work

Below is the stackblitz link to code: https://stackblitz.com/edit/typescript-btkudb?file=index.ts

Svibhor
  • 53
  • 10
  • 1
    because on every click you're creating a new subscription without unsubscribing the previous one – martin Feb 17 '21 at 09:52
  • What is the expected result u want – Msk Satheesh Feb 17 '21 at 09:53
  • switchMap should cancel the the previous results and only emit the new results but in this case it starts a new result without canceling the previous one – Svibhor Feb 17 '21 at 09:55
  • Because every time you have a new observable, I recommend to you to read that: https://vdsabev.medium.com/the-simple-difference-between-rxjs-switchmap-and-mergemap-397c311552a5 – StPaulis Feb 17 '21 at 09:57
  • @martin how can I unsubscribe the previous one in this case ? – Svibhor Feb 17 '21 at 10:02
  • 1
    I would recommend that you use RxJS's `fromEvent` instead of adding an event listener manually – ShamPooSham Feb 17 '21 at 10:13

1 Answers1

0

You seem to have already imported RxJS fromEvent function but instead opted to use addEventListener(). I'd say fromEvent suits better here since you're trying to pipe in RxJS operators to the event. You could try something like

import { interval, fromEvent, of } from "rxjs";
import { map, tap, switchMap } from "rxjs/operators";

fromEvent(<HTMLElement>document.querySelector("#app"), "click")
  .pipe(
    tap(_ => console.log("clicked")),
    map(_ => of("test")),              // <-- serves no purpose?
    switchMap(() => interval(1000))
  )
  .subscribe(console.log);

I've modified your Stackblitz.

Working example:

var { interval, fromEvent, of } = rxjs;
var { map, tap, switchMap } = rxjs.operators;

fromEvent(document.querySelector("#app"), "click").pipe(
  tap(_ => console.log("clicked")),
  map(_ => of("test")),              // <-- serves no purpose?
  switchMap(() => interval(1000))
).subscribe(console.log);
<script src="https://unpkg.com/rxjs@6.4.0/bundles/rxjs.umd.min.js"></script>

<div id="app">abcd</div>

Moreover, while I appreciate the working example in the question, it's always better to write the code in the question instead of only linking to an external website. It ensures question's longevity.

ruth
  • 29,535
  • 4
  • 30
  • 57
  • What should I do If I want to call switchMap over an string, like below code and this function is when user types something in the input ? function search(query){ of(query) .pipe( // restart counter on every click switchMap((query) => this.http.getDetails(query)) ) .subscribe(console.log); console.log("clicked"); } – Svibhor Feb 17 '21 at 11:06
  • I have updated the code in the stackblitz for current issue. If we call it inside a function then switchmap does not work https://stackblitz.com/edit/typescript-btkudb?file=index.ts – Svibhor Feb 17 '21 at 12:23
  • You're misunderstanding RxJS observables and also running into the [XY problem](https://meta.stackexchange.com/q/66377). You can't just slap an `of` to something and expect it to be shared by the piped `switchMap`. For that you'd need to use a multicast like `Subject`. But actual issue presumably doesn't have anything to do with it. Please post the actual requirement with the user input instead of an abstracted code. – ruth Feb 17 '21 at 12:33
  • Each call to `foo()` initialized a separate observable with it's own `switchMap` operator. So there are actually 3 simultaneous `of()` with it's own `switchMap`. For the `switchMap` to cancel the old stream, the notifications must be emitted from it's source observable. – ruth Feb 17 '21 at 12:35
  • I have updated the stackblitz with updated code and added a detailed explanation of the issue. Please suggest – Svibhor Feb 17 '21 at 13:38