2017-07-01 8 views
1

Ich versuche herauszufinden, wie async/erwarten in meinen angularen Klassen verwenden. Ich habe einen PostService, der Posts von einem API erhält, ist aber auf den AreaService angewiesen, so dass PostService weiß, aus welchem ​​Bereich der Post kommt. Kann mir nicht vorstellen, wie ich meiner Winkelklasse PostService mitteilen soll, auf Daten von meinem AreaService zu warten. Eine korrekte Antwort von AreaService wäre die Zeichenfolge "Spaß". PostService würde dann diese Fun-Zeichenfolge im this.areas-Array verwenden, um dem Benutzer Beiträge aus dem aktuell ausgewählten Bereich anzuzeigen. Der aktuelle Fehler lautet: Uncaught (in promise): Fehler: Fehler in: 0: 0 verursacht durch: Eigenschaft kann nicht gelesen werden 'name' undefinierterVerwendung von Async/Wartefunktion in Winkel 2

Postservice

import { Injectable, OnDestroy } from '@angular/core'; 
     import { Http, Headers, RequestOptions, Response } from '@angular/http'; 
     import { Observable} from 'rxjs'; 
     import 'rxjs/add/operator/map'; 

     import { AuthenticationService, AreaService, MessageService} from './index'; 
     import { Post, Area} from '../_models/index'; 

     @Injectable() 
     export class PostService { 
      areas: Area[] = []; 
      constructor(
       private http: Http, 
       private authenticationService: AuthenticationService, 
       private areaService: AreaService, 
       private messageService: MessageService 
      ) { 

      } 

      getPosts(): Observable<Post[]> { 
       this.areaService.getAreas().subscribe(area => { this.areas = area;}); 

      // add authorization header with jwt token 
      let headers = new Headers(); 
      headers.append('Authorization','token ' + this.authenticationService.token); 

      headers.append('Content-Type', 'application/json'); 
      let options = new RequestOptions({ 

      headers: headers 
     }); 

      // get posts from api 
      return this.http.get('http://localhost:8000/areas/'+ this.areas[0].name +'/', options) 
       .map((response: Response) => response.json()); 

     } 
     } 

areaservice

import { Injectable } from '@angular/core'; 
    import { Http, Headers, RequestOptions, Response } from '@angular/http'; 
    import { Observable, Subject } from 'rxjs'; 
    import 'rxjs/add/operator/map'; 

    import { AuthenticationService, MessageService } from './index'; 
    import { Area } from '../_models/index'; 

    @Injectable() 
    export class AreaService { 
     public areas: Observable<Area[]> ; 
     subject:Subject<Area[]> = new Subject(); 
     public currentArea: string = "fun"; 
     constructor(
      private http: Http, 
      private authenticationService: AuthenticationService, 
      private messageService: MessageService) { 
     } 

     getAreas(): Observable<Area[]> { 

      // add authorization header with jwt token 
      let headers = new Headers(); 
      headers.append('Authorization','token ' + this.authenticationService.token); 

      headers.append('Content-Type', 'application/json'); 
      let options = new RequestOptions({ 
      headers: headers 
      }); 
      // get areas from api 
      return this.http.get('http://localhost:8000/areas/', options) 
       .map((response: Response) => response.json()); 

       // this.areas = response.json(); 
      //  console.log("h"); 
      //  this.messageService.sendMessage(this.areas[0].name); 


    //this.messageService.sendMessage(this.areas[0].name); 
     } 
    } 

area.ts

import { Injectable } from '@angular/core'; 
    @Injectable() 
    export class Area{ 
     name:string; 
     currentArea:number = 1; 

     constructor(name:string) { 
      this.name = name; 
     } 

     public static createEmptyrea():Area{ 
      return new Area(""); 
     } 
     setArea(val:number) { 
      this.currentArea = val; 
     } 

    } 

eingehender json aus/areas/

[ 
     { 
      "name": "fun" 
     }, 
     { 
      "name": "information" 
     } 
    ] 

Antwort

3

Sie nicht async/await benötigen, wenn Sie mit Observablen arbeiten. Sie müssen mergeMap Operator für [email protected] oder flatMap für [email protected] verwenden:

getPosts(): Observable<Post[]> { 
    // subscribe until the area is available 
    return this.areaService.getAreas().mergeMap(area => { 

     // add authorization header with jwt token 
     let headers = new Headers(); 
     headers.append('Authorization', 'token ' + this.authenticationService.token); 

     headers.append('Content-Type', 'application/json'); 
     let options = new RequestOptions({ 

      headers: headers 
     }); 

     // use the area to get the response 
     return this.http.get('http://localhost:8000/areas/' + area.name + '/', options) 
      .map((response: Response) => response.json()); 
    }); 
} 
+0

Nach der Implementierung es sagt mir, dass eine Funktion, die weder nichtig ist oder jeder muss zurückkehren ein Wert –

+0

@CameronGilbert, yeah, einfach 'return' vor 'this.areaService.getAreas(). mergeMap ... 'hinzufügen. Ich habe die Antwort aktualisiert –

+1

Arbeitet dank +1 –

2

Sie flatMap oder mergeMap verwenden können:

getPost(): Observable<Post[]> { 
    return this.http.get('http://localhost:8000/areas/', options) 
    .map((res: any) => res.json()) 
    .flatMap((area: any) => { 
     return this.http.get('http://localhost:8000/areas/'+ area[0].name +'/', options) 
     .map((response: Response) => response.json());  
     .map((res: any) => res.json()); 
    }); 
}