简体   繁体   中英

Angular2 - Multiple service calls in OnInit method of component

How can I make two service calls in the OnInit() method of the component ?

export class ApartmentComponent implements OnInit {
    public apartments: Object[];
    public temp: Object[];

    constructor(private apartmentService: ApartmentService) {
    this.apartmentService = apartmentService;
    }

    ngOnInit() {
    this.apartmentService.getApartments().subscribe(res => this.apartments = res);

    this.apartmentService.getStats().subscribe(res => this.temp = res);

    console.log(JSON.stringify(this.temp));
    }
}

In service.ts

getApartments() {
    return this.http.get('./api/businessunits/butype').map((res: Response) => res.json());
}

getStats(){ 
    console.log('Request reached');
    return this.http.get('./api/apartments/getstats').map((res: Response) => res.json());
} 

in server.ts (ExpressJS)

router.route('/api/businessunits/butype')             
.get(function(req, res) {
    BusinessUnit.find({unitID: {$exists: true}, UnitType: {$exists:  true}},'unitID UnitType',{sort:{unitID: 1}},function(err, businessunits) {
        if (err)
            res.send(err);

        res.json(businessunits);
     });
});

router.route('/api/apartments/getstats')             
.get(function(req, res) {
    //Apartment.aggregate([{$match:{_id: "aptType"}},{$group:{_id:{aptType:"$aptType"},count:{$sum:1}}}],function(err, apartments) {
      Apartment.find('aptType',function(err, apartments) {
        if (err)
            res.send(err);
        res.json(apartments);
     });
}); 

The getApartments() works fine individually when I comment out getStats() method call.

I am getting the following error

Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:335:11)
at ServerResponse.header (M:\workspace\Angular2StartKit\node_modules\express

Subscribing to observables is an async operation, that means this just schedules a tasks to be done later.

When console.log(JSON.stringify(this.temp) is executed, the call to the server in getStats() (if it actually makes one - I just assume it does) wasn't even sent, and therefor definitely no response received yet.

It is also not clear from the code in your question whether the request for getApartments() or getStats() is sent first.

To preserve a specific order in async operations, you need to chain them properly so that the next is executed when the former is completed.

If you just want to print the result of getStats() this can be done like

ngOnInit() {
  this.apartmentService.getApartments().subscribe(res => this.apartments = res);

  this.apartmentService.getStats().subscribe(res => {
    this.temp = res;
    JSON.stringify(this.temp)
  });
}

alternatives are

ngOnInit() {
  this.apartmentService.getApartments().subscribe(res => this.apartments = res);

  this.apartmentService.getStats()
  .map(res => this.temp = res);
  .subscribe(temp => console.log(JSON.stringify(this.temp));
  });
}

or

ngOnInit() {
  this.apartmentService.getApartments().subscribe(res => this.apartments = res);

  this.apartmentService.getStats()
  .map(res => this.temp = res);
  .toPromise().then(temp => console.log(JSON.stringify(this.temp));
  });
}

If you want to chain 2 subscribes

this.apartmentService.getApartments().subscribe(res => this.apartments = res);
this.apartmentService.getStats().subscribe(res => this.temp = res);

there are lots of possiblilities like flatMap() depending on your requirements. You might want that they are sent one after the other is completed, or send both as soon as possible but then wait for both to complete. There are different ways to handle errors, ...

For more details see http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM