1

I am new to Rxjs and am trying to implement the following workflow in it:

  1. User clicks on a menu item that triggers an HTTP request
  2. Before the response has arrived, the user clicks on a second request
  3. The subscription to the first request is ended and a subscription to the second request is started

    // The code below sits inside the onClick event of my menu
    var callAction = function(someParameters) {
                return Rx.Observable.create(function(observer) {
                    var subscribed = true;
                    myHttpApi.someActionCall(someParameters).then(
                        (data: any) => {
                            if (subscribed) {
                                // Send data to the client
                                observer.next(data);
                                // Immediately complete the sequence
                                observer.complete();
                            }
    
    
                        }).catch((err: any) => {
                            if (subscribed) {
                                // Inform the client that an error occurred.
                                observer.error(ex);
                            }
    
                        }
                    );
                    return function () {
                        subscribed = false;
                    }
                });
            };
    

The observer is further defined below:

var observer = {
                // onNext in RxJS 4
                next: function (data) {
                    // Do what you need to do in the interface
                },
                // onError in RxJS 4
                error: function (err) {
                    // Handle the error in the interface
                },
                // onComplete in RxJS 4
                complete: function () {
                    //console.log("The asynchronous operation has completed.");
                }
            };

            let subscription = callAction(somParameters).subscribe(observer);

How do I now go about implementing #3, whereby the subscription to the first request is ended and a subscription to the new request (in this example, the same block of code is executed for different menu options and therefore different requests based on the parameters) is started?

Somik Raha
  • 171
  • 1
  • 10
  • Look at example 2: https://www.learnrxjs.io/operators/transformation/switchmap.html and use `Rx.Observable.from` to wrap the promise, but be aware that promises are not cancellable. You might want to consider using an [RxJS AJAX observable](https://stackoverflow.com/a/41288856/6680611) instead. – cartant Oct 27 '17 at 01:42
  • You probably looking at a queuing pattern like this https://stackoverflow.com/questions/46469442/pattern-for-observables-that-includes-acknowledgement/46472309#46472309 – Fan Cheung Oct 27 '17 at 02:22
  • @FanCheung The pattern here is different -- instead of waiting for the previous one to complete, I want the previous one to be aborted and the next one to be the one that we are subscribed to. How might that be done? – Somik Raha Oct 27 '17 at 03:35
  • @cartant Thank you! switchmap might be just what I need -- will try. – Somik Raha Oct 27 '17 at 03:48

1 Answers1

3

Breaking up the steps into discrete functions,

// Inner observable, calls the API
const callAction$ = function(someParameters) {
  return Observable.fromPromise(
    myHttpApi.someActionCall(someParameters)
  ) 
}

// Outer observable, controls the click chain
const click$ = new Subject();
click$.switchMap(clickParams => {
  return callAction$(clickParams)
})
.subscribe(
  result => console.log('Result: ', result), 
  err => console.log('Error: ', err.message)
)

// Handler function, called from menu
const handleClick = function(clickParams) {
  click$.next(clickParams)
}

Working example CodePen

Richard Matsen
  • 20,671
  • 3
  • 43
  • 77