Angular 4将某些JSON数据映射到类并返回可观察的数据

时间:2017-09-07 18:08:15

标签: json angular typescript

所以我试图通过创建一个使用OpenWeather API获取和显示位置当前天气的应用程序来学习一些基本的Angular。

这就是我目前代码中的内容:

app.component.ts:

import { Component } from '@angular/core';
import { WeatherService } from './weather.service';    
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [WeatherService]
})    
export class AppComponent {
  title = 'Ng-Weather';
  cityName: string;
  weather: Weather;    
  constructor(private weather: WeatherService) { }    
  search() {
    this.weather.getWeatherbyName(this.cityName)
      .subscribe(res => this.weather = res);
    console.log(this.weather);
  }
}

weather.service.ts:

import { Injectable } from '@angular/core';
import { Http, Response, URLSearchParams } from '@angular/http';
import { Observable } from 'rxjs';
import { Weather } from './weather';
@Injectable()
export class WeatherService {
  APIurl = "http://api.openweathermap.org/data/2.5/weather";
  Appid = "xxx";
  weather: Weather;
  constructor(private http: Http) { }
  getWeatherbyName(name: string): Observable<any> {
    let myParams = new URLSearchParams();
    myParams.append('appid', this.Appid);
    myParams.append('q', name);
    return this.http.get(this.APIurl , { search: myParams} )
      .map(this.extractData)
      .catch(this.handleError);
  }
  private extractData(res: Response) {
    let body = res.json();
    this.weather.city = body.name;
    this.weather.description = body.weather[0].main;
    this.weather.temp = body.main.temp;
    console.log(this.weather);
  }
  private handleError(error: Response | any) {
    console.error(error.message || error);
    return Observable.throw(error.message || error);
  }
}

weather.ts:

export class Weather {
    city: String;
    description: String;
    temp: String;
}

所以基本上我试图映射从OpenWeather API返回的JSON,只获取数据的某些部分而不是整个部分。返回的JSON如下:

{  
    "coord":{  
        "lon":80.28,
        "lat":13.09
    },
    "weather":[  
        {  
            "id":802,
            "main":"Clouds",
            "description":"scattered clouds",
            "icon":"03n"
        }
    ],
    "base":"stations",
    "main":{  
        "temp":303.15,
        "pressure":1008,
        "humidity":79,
        "temp_min":303.15,
        "temp_max":303.15
    },
    "visibility":6000,
    "wind":{  
        "speed":3.1,
        "deg":210
    },
    "clouds":{  
        "all":40
    },
    "dt":1504805400,
    "sys":{  
        "type":1,
        "id":7834,
        "message":0.0017,
        "country":"IN",
        "sunrise":1504744074,
        "sunset":1504788314
    },
    "id":1264527,
    "name":"Chennai",
    "cod":200
}

执行上述代码时,出现此错误:

weather.service.ts:32 Cannot set property 'city' of undefined

另外,如何返回类型为Weather的observable并返回该变量天气并在app.component.ts上捕获它?

1 个答案:

答案 0 :(得分:5)

在分配属性之前,您不是在创建天气对象的实例。你可以这样明确地做到这一点:

this.weather = new Weather();
this.weather.city = body.name;
this.weather.description = body.weather[0].main;
this.weather.temp = body.main.temp;
console.log(this.weather);

OR

您可以这样做:

this.weather = { 
                 city: body.name,
                 description: body.weather[0].main,
                 temp: body.main.temp
               }
console.log(this.weather);

要回答问题的第二部分,您应该可以这样做:

  getWeatherbyName(name: string): Observable<Weather> {
      // your other code
  }

  private extractData(res: Response) {
    // your other code
    return this.weather;
  }

回答问题的第三部分...... Observables是异步的。这意味着它们不会立即返回值。相反,它们提供了在返回数据时执行的回调函数的定义。这意味着数据未定义,直到返回数据并执行回调函数。

因此,如果要访问代码中返回的数据,则需要在 WITHIN 中执行回调函数。像这样:

  search() {
    this.weather.getWeatherbyName(this.cityName)
      .subscribe(res => {
             this.weather = res;
             console.log(this.weather);
      });
  }