1

If I have an event type; say a click event. That I want to fire 3 unique ajax requests for but I want to subscribe to the final result of all 3 requests

What is the proper design pattern for this sequence.

My current code block looks something like this

$rootScope.$eventToObservable('selectUser')
    .throttle(500)
    .map(data => {
        return angular.copy(data.additionalArguments[0].entity);
    })
    .select(d => {
        return {
            Member: MemberService.getMember(d.ID),
            otherData: MemberService.dataOtherData(d.ID),
            Notes: MemberService.getNotes(d.ID),
            Log: MemberService.getLog(d.ID)
        }
    })
    .switchLatest() //Code current dies here with an object is not a function error. I believe because the return object is not an obserable. But not sure what the proper design pattern is.
    .subscribe(model => {
        //I would like that model would contain an object with the result of the 3 responses above.
        $scope.model = model;
});
Jonathan Sheely
  • 501
  • 1
  • 6
  • 13
  • 1
    I missing bit of the code. all the MemberService.get methods return a promise `var deferred = this.$http.get(ServiceUrl + '/Users/Get/' + id); return this.rx.Observable.fromPromise(deferred).map((response) => { return response.data; });` – Jonathan Sheely Jul 18 '14 at 03:19

1 Answers1

4

You can use zip to synchronize your requests. zip will cause all observables to be subscribed, and yield each time all of those observables fire. So, once the nth item from each observable is yielded, zip will yield it's nth value, which is created by using the nth values from the original observables.

Once you have that, can you use switchLatest, which works on Observable<Observable<T>>, and makes sure it's always subscribed to the latest observable. So, if you select a new user, it'll just unsubscribe from any pending request, and subscribe to the next one instead.

$rootScope.$eventToObservable('selectUser')
    .throttle(500)
    .map(data => {
        return angular.copy(data.additionalArguments[0].entity);
    })
    .map(entityToExpandedData).switchLatest()
    .subscribe(model => {
        $scope.model = model;
    });

function entityToExpandedData (entity) {
    return Rx.Observable
        .zip(
            MemberService.getMember(d.ID),
            MemberService.dataOtherData(d.ID),
            MemberService.getNotes(d.ID),
            MemberService.getLog(d.ID),
            makeExpandedData
        );
}

function makeExpandedData (member, otherData, notes, log) {
    return {
        member:     member,
        otherData:  otherData,
        notes:      notes,
        log:        log
    };
}
cwharris
  • 17,835
  • 4
  • 44
  • 64
  • Thanks Chris, I like your implementation. It looks like actual issue us the `return angular.copy...` I tried replacing it with just a simple ID `return 123` and I get object is not a function from Disposable.dispose. Am I miss understanding the map function? I can return any object, type I want correct? Even single values? string, int, etc. – Jonathan Sheely Jul 18 '14 at 04:01
  • Ultimately your answer for Rx.Observable.zip() answered my question. However there were 2 bugs. Firstly .zip() took a series of functions with the last one before the makeExpandedData. Not an array[] of api requests. Secondly the main issue I had was that the rx.angular $eventToObservable was firing the dispose event for some reason. – Jonathan Sheely Jul 18 '14 at 06:23
  • You're right! It's `.zip(a,b,c,...)`. Interesting though. I feel like I've used `.zip([a,b,c], ...)` before... oh well. Can you expand on what you mean by $eventToObservable firing the "dispose event"? – cwharris Jul 18 '14 at 23:54
  • @ChristopherHarris When you use zip this way, are the server response objects in the array in the same order as the requests are listed? – claireablani Oct 20 '16 at 03:52
  • @claireablani `switchLatest` will only yield results from the latest observable, therefore the order of results will be maintained, but results yielded from prior observable will filtered out. – cwharris Nov 02 '16 at 19:57