1

So I use switchMap() to cancel out HTTP calls and keep only the last call to the server... Here is the service:

function httpService(url) {
   // httpRequest$ stream that allows us to push new requests
   const httpRequest$ = new Rx.Subject();

   // httpResponse$ stream that allows clients of the httpService
   // to handle our responses (fetch here can be replaced with whatever
   // http library you're using).
   const httpResponse$ = httpRequest$
       .switchMap(() => fetch(url));


   // Expose a single method get() that pushes a new
   // request onto the httpRequest stream. Expose the
   // httpResponse$ stream to handle responses.
   return {
       get: () => httpRequest$.next(),
       httpResponse$
   };
}

and the component using this service:

const http = httpService('http://my.api.com/resource');

// Subscribe to any responses
http.httpResponse$.subscribe(resp => console.log(resp));

// Call http.get() a bunch of times: should only get one log!!
http.get();
http.get();
http.get();

This works fine for one component... BUT, the issue is that if I call httpService(url) from different components I will still get MULTIPLE instances of HTTP streams, and sure, it will only be a SINGLE stream per component (due to switchMap() canceling out repetitive http.get() PER SAME component)... my goal is to have ALL calls from all components be canceled out and only the last one sent to server, be accounted for.

What I am missing is the ability to merge all the streams together from the different components inside of httpService and have switchMap() only deal with the last last last one... tricky... :/

1
  • If I understand what you want to do you need to use services angular.io/docs/ts/latest/tutorial/toh-pt4.html and share one instance of httpRequest$ instead of creating the httpService() in every component. Commented Sep 19, 2016 at 15:18

2 Answers 2

1

Don't directly return observable from request, but create observable from data. Something like this:

function httpService(url) {
   const httpRequest$ = new Rx.Subject();
   let httpResponse$ = new Rx.Subject();

   httpRequest$.switchMap(() => fetch(url)).subscribe(data => httpResponse$.next(data))

   return {
       get: () => httpRequest$.next(),
       httpResponse$
   };
}
Sign up to request clarification or add additional context in comments.

3 Comments

unfortunately I am getting just more xhr requests with this setup :(
Do you have a plunker with example?
I don't but I will set one up... tx
0

constructor(private _http:Http, private appStore:AppStore) {

    this.httpRequest$ = new Subject();


    this.httpRequest$
        .map(v=> {
            return v;
        })
        .switchMap((v:any):any => {
            console.log(v);
            if (v.id==-1||v.id=='-1')
                return 'bye, cancel all pending network calls';                
            return this._http.get('example.com)
                .map(result => {
                    var xmlData:string = result.text()
                });
        }).share()
        .subscribe(e => {                
        })
    ...

and to push data in:

this.httpRequest$.next({id: busId});        

this works great and I can now have a single service that I can pipe all network calls through as well as cancel prior calls...

see image below, as new calls come in, prior ones are canceled. note how I set slow network with a delay of 4sec to provide all is working as expected...

enter image description here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.