typescript - Usando función async/await en angular 2
Estoy intentando averiguar cómo usar async/await en mis clases de Angular. Tengo un PostService que obtiene publicaciones de una API, pero depende del AreaService para que PostService sepa de qué área obtener la publicación. No consigo entender cómo decirle a mi clase de Angular PostService que espere los datos de mi AreaService. Una respuesta correcta de AreaService sería la cadena "fun". PostService usaría entonces esta cadena "fun" en el array this.areas para mostrar publicaciones al usuario desde el área seleccionada actualmente. El error actual es: Uncaught (in promise): Error: Error en :0:0 causado por: Cannot read property 'name' of undefined
postservicio
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());
}
}
servicio de área
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);
}
}
área.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;
}
}
json entrante desde /areas/
[
{
"name": "fun"
},
{
"name": "information"
}
]
Respuesta #1
No necesitas async/await si estás trabajando con observables. Necesitas usar el operador mergeMap para rxjs@5 o flatMap para rxjs@4:
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());
});
}
Respuesta #2
Puedes usar flatMap o mergeMap:
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());
});
}
