1

In my data service I have:

//Observables
currentTicket$: Observable<Ticket>;
ticketTypes$: Observable<Array<TicketType>>;
currentTicketSurvey$: Observable<TicketSurvey>;


//observers
private _ticketTypesObserver: any;
private _currentTicketSurveyObserver: any;
private _currentTicketObserver: any;

private _dataStore: {
    currentTicket: Ticket,
    ticketTypes: Array<TicketType>,
    currentTicketSurvey: TicketSurvey
}

constructor(private http: Http){
//set up observables
this.currentTicket$ = new Observable(observer=> this._currentTicketObserver = observer).share();
    this.ticketTypes$ = new Observable(observer=> this._ticketTypesObserver = observer).share();
    this.currentTicketSurvey$ = new Observable(observer=> this._currentTicketSurveyObserver = observer).share();


//init datastore
this._dataStore = {
        currentTicket: null,
        ticketTypes: [],
        currentTicketSurvey: null
    };
}



//Data Retrieval Methods

getTicketTypes() {
    if (this._dataStore.ticketTypes.length > 0) //if we already have ticket types, don't refresh.  Static Data.
        return;

    this.http.get('http://localhost:65421/tickets/GetTicketTypes/')
        .map(res => (<Response>res).json())
        .map((types: Array<any>) => {
            let result: Array<TicketType> = [];
            if (types) {
                types.forEach(ticketType => {
                    result.push(
                        new TicketType(
                            ticketType.Description
                            , ticketType.Id
                            , ticketType.IsDisplayed
                        ));
                });
            }

            return result;
        }).
        subscribe(
        data => {
            this._dataStore.ticketTypes = data;
            this._ticketTypesObserver.next(this._dataStore.ticketTypes);
        },
        err => {
            console.log(err);
        }
        );
}


getTicketSurvey(ticketId:string) {

    this.http.get('http://localhost:65421/tickets/GetTicketById/' + ticketId)
        .map(res => (<Response>res).json())
        .map((survey: TicketSurvey) => {
            let result: TicketSurvey = null;
            if (survey) {
                result = new TicketSurvey(
                    survey.id,
                    survey.ticketId,
                    survey.ticketTypeId
                );
            }

            return result;
        }).
        subscribe(
        data => {
            this._dataStore.currentTicketSurvey = data;
            this._currentTicketSurveyObserver.next(this._dataStore.currentTicketSurvey);
        },
        err => {
            console.log(err);
        }
        );
}


getTicketById(id:string) {
    this.http.get('http://localhost:65421/tickets/GetTicketById/' + id)
        .map(res => (<Response>res).json())
        .map((ticketRes: Ticket) => {
            let result: Ticket = null;
            if (ticketRes) {
                result = new Ticket(
                    //Set constructor values
                );
            }

            return result;
        }).
        subscribe(
        data => {
            this._dataStore.currentTicket = data;
            this._currentTicketObserver.next(this._dataStore.currentTicket);
        },
        err => {
            console.log(err);
        }
        );
}

My component has:

currTicket: Ticket;
ticketTypes: Array<TicketType>;
currTicketType: TicketType;
currTicketSurvey: TicketSurvey;


ngOnInit() {
    this.ticketDataService.currentTicket$.subscribe(cTicket => this.currTicket = cTicket);
    this.ticketDataService.ticketTypes$.subscribe(tTypes => this.ticketTypes = tTypes);
    this.ticketDataService.currentTicketSurvey$.subscribe(cSurvey => this.currTicketSurvey = cSurvey);

    this.load();
}

load()
{
    this.ticketDataService.getTicketById(this._routeParams.get('id'));
    this._ticketDataService.getTicketTypes();
    this._ticketDataService.getTicketSurvey(this._routeParams.get('id'));

    //////************ Need something here to set the current ticket type

    //this.ticketTypes.forEach((tType)=>{
    //    if(tType.id == this.currTicketSurvey.ticketTypeId)
    //    this.currTicketType = tType;
    //    return;
    //});

}

The problem I am having is how do I set the currentTicketType in the component? it depends on the currentTicketSurvey having been loaded and on the ticketTypes having been loaded. These may or may not be called together in other areas of my code and since they are async calls I can't just set it right after I call them on the service. In knockout I think I could just set a computed observable and be done with it. I can't find an equivalent for Angular 2. Any ideas on how to handle this situation to get the currentTicketType to be set once the other objects are loaded?

Surely it comes up often. The examples I've seen that are similar but not the same say to use defer and concatAll but that looks like it would assume these methods would always be called in the same order or at the same time. I just haven't been able to piece together what I'm looking for yet.

Reagan L
  • 79
  • 1
  • 1
  • 7

1 Answers1

2

RxJS provides a set of combining operators and I think that Observable.forkJoin or Observable.merge could fit your needs.

  • Observable.forkJoin will wait for a set of observables to have received events (each one):

    Observable.forkJoin([a,b]).subscribe(t=> {
      var firstResult = t[0];
      var secondResult = t[1];
    });
    
  • Observable.merge. The stream is closed when 2 results are received

    Observable.merge(obs1, obs2)
     .take(2)
     .subscribe({complete: () => { ... });
    

This question could give you some additional hints:

Community
  • 1
  • 1
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • I am gonna mark this as the answer even though I cannot get my code to work. I think the reason my code is not working is not related to this. Thanks for the help. – Reagan L Feb 22 '16 at 15:50