1
votes

Hello I'm new to RxJS and I'm just getting to know operators. I want to show in console next 6 numbers in one-second time interval after button click. I want to reset that counter after next click using switchMap.

I've been trying to do with switchMap, but counter is not reseting.

obsSwitchMap: Observable<any>;

this.obsSwitchMap = of(null).pipe(
  switchMap(x => from([1, 2, 3]).pipe(
    concatMap(item => of(item).pipe(delay(300)))
    )
  )  
)

onSwitchMapBtnClick() {
  this.obsSwitchMap.subscribe(x => {
    console.log(x)
  })
}

Numbers are displaying independently of each other

2

2 Answers

0
votes

Although you want to learn, I think you should learn with the best practices from the start.

And it means you can do it very simply without switchMap :

const newInterval = () => rxjs.timer(0, 1000).pipe(
  rxjs.operators.map(nb => new Array(6).fill(nb).map((v, i) => v + i + 1))
);

let subscription;

function resetTimer() {
  subscription && subscription.unsubscribe();
  subscription = newInterval().subscribe(v => console.log(v));
}

resetTimer();
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.2/rxjs.umd.js"></script>

<button onclick="resetTimer()">Reset timer</button>

EDIT

Here is a switchMap example :

const horsemen = [
  { id: 1, name: 'Death' },
  { id: 2, name: 'Famine' },
  { id: 3, name: 'War' },
  { id: 4, name: 'Conquest' },
];

// Fake HTTP call of 1 second
function getHorseman(id) {
  return rxjs
    .of(horsemen.find(h => h.id === id))
    .pipe(rxjs.operators.delay(1000));
}

const query = document.querySelector('input');
const result = document.querySelector('div.result');

// Listen to input
rxjs.fromEvent(query, 'input')
  .pipe(
    rxjs.operators.map(event => +event.target.value), // Get ID
    rxjs.operators.switchMap(id => getHorseman(id)) // Get Horseman
  ).subscribe(horseman => {
    let content;
    if (horseman) content = `Horseman = ${horseman.name}`;
    else content = `Horseman unknown`;
    result.innerText = content;
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.2/rxjs.umd.js"></script>

<input type="text" placeholder="Input an ID here (1-4)">

<div class="result"></div>
0
votes

I have found simply solution using switchMap. On every click, restart your observable counter and take how many items you want.

const btn = document.querySelector('button');

fromEvent(btn, 'click').pipe(
    switchMap((item => interval(1000).pipe(take(6)))),
).subscribe(console.log)