Search code examples
rxjsobservablerxjs-observablesrxjs-pipeable-operators

call two different methods based on emissions of two observables


currently, I have a cabinet with some drawers, each drawer has some items that users can manipulate. Whenever the user switches to a different drawer an observable (D) fires. As soon as the user swithces to a drawer, another observable (I) fires with an array of Items available in that drawer. My desired behaviour is for the follwoing stream:

Drawer(D): --D----------------------------D--...
Items(I): -------I----I-----I-----I-----I----I--..

for an emission (D) and first following emission (I) => call a function (setCurrentDrawerItems())

for all following emissions of (I) that are not interrupted by an emission (D) => call the function (userPickedItemFromDrawer())

how can I achieve this using rxjs operators?


Solution

  • One approach is to tag your observable emissions to cleanly separate the two in the merged stream. For example, shoving them into an object with the label t. Then you can just query that label to know what to do next.

    Something like this might work:

    merge(
    
      drawer$.pipe(map(v => ({ t: 'D', v }))),
      items$.pipe(map(v => ({ t: 'I', v })))
    
    ).pipe(
    
      startWith({ t: 'I', v: null }), 
      pairwise()
    
    ).subscribe(([prev, curr]) => {
    
      if (curr.t == 'D' || (curr.t == 'I' && prev.t == 'D')) {
        setCurrentDrawerItems(curr.v);
      } else {
        userPickedItemFromDrawer(curr.v);
      }
      
    });