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

Jac*_*r94 0 json typescript angular

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

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

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

weather.ts:

export class Weather {
    city: String;
    description: String;
    temp: String;
}
Run Code Online (Sandbox Code Playgroud)

所以基本上我试图映射从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
}
Run Code Online (Sandbox Code Playgroud)

执行上面的代码时,我收到此错误:

weather.service.ts:32 Cannot set property 'city' of undefined
Run Code Online (Sandbox Code Playgroud)

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

Deb*_*ahK 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);
Run Code Online (Sandbox Code Playgroud)

要么

你可以这样做:

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

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

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

  private extractData(res: Response) {
    // your other code
    return this.weather;
  }
Run Code Online (Sandbox Code Playgroud)

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

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

  search() {
    this.weather.getWeatherbyName(this.cityName)
      .subscribe(res => {
             this.weather = res;
             console.log(this.weather);
      });
  }
Run Code Online (Sandbox Code Playgroud)