地图不是一个功能

时间:2017-01-21 12:11:05

标签: web-services angular

我正在尝试创建一个与天气api相关联的网站,并获取有关特定城市当前天气的信息。当我在我的应用程序中查看网络流程时,我确实收到了包含该信息的json,但我无法映射它并显示结果。错误我的建议是:

TypeError: response.json(...).map is not a function     WeatherSearchComponent.ts:138
at MapSubscriber.project (WeatherSearchComponent.ts:84)
at MapSubscriber._next (map.js:77)
at MapSubscriber.Subscriber.next (Subscriber.js:89)
at XMLHttpRequest.onLoad (http.umd.js:1083)
at ZoneDelegate.invokeTask (zone.js:225)
at Object.onInvokeTask (core.umd.js:6004)
at ZoneDelegate.invokeTask (zone.js:224)
at Zone.runTask (zone.js:125)
at XMLHttpRequest.ZoneTask.invoke (zone.js:293)

Heres WeatherSearchComponent:

import {
  Component,
  Injectable,
  OnInit,
  ElementRef,
  EventEmitter,
  Inject
} from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs';
import 'rxjs/Rx';
import 'rxjs/add/operator/map';



export var WEATHER_API_KEY: string = 'api_key';
export var WEATHER_API_URL: string ='http://api.openweathermap.org/data/2.5/weather';
export var GDANSK_ID: string = '3099434';

/*let loadingGif: string = ((<any>window).__karma__) ? '' :
 require('images/loading.gif');*/

class SearchResult {
  content: string;

  constructor(obj?: any) {
    this.content= obj && obj.content ||
     WEATHER_API_URL + 'id=' + obj.city + 'appid=' + WEATHER_API_KEY;
  }
}

// http://api.openweathermap.org/data/2.5/weather?
// id=3099434&appid=api_key

@Injectable()
export class WeatherService {
  constructor(private http: Http,
              @Inject(WEATHER_API_KEY) private apiKey: string,
              @Inject(WEATHER_API_URL) private apiUrl: string) {
  }

  search(city: string): Observable<SearchResult[]> {
    let params: string = [
      `q=${city}`,
      `appid=${this.apiKey}`
    ].join('&');
    let queryUrl: string = `${this.apiUrl}?${params}`;
    console.log("query url" , queryUrl);
    var getRequest = this.http.get(queryUrl);
    console.log("getRequest", getRequest);
    return getRequest
      .map((response: Response) => {
        return (<any>response.json()).map(item => {
          console.log("raw item", item); // uncomment if you want to debug
          return new SearchResult({
            content: item.main.temp
          });
        });
      });
  }
}

export var weatherServiceInjectables: Array<any> = [
  {provide: WeatherService, useClass: WeatherService},
  {provide: WEATHER_API_KEY, useValue: WEATHER_API_KEY},
  {provide: WEATHER_API_URL, useValue: WEATHER_API_URL}
];

/**
 * SearchBox displays the search box and emits events based on the results
 */

@Component({
  outputs: ['loading', 'results'],
  selector: 'search-box',
  template: `
    <input type="text" class="form-control" placeholder="Search" autofocus>
  `
})
export class SearchBox implements OnInit {
  loading: EventEmitter<boolean> = new EventEmitter<boolean>();
  results: EventEmitter<SearchResult[]> = new EventEmitter<SearchResult[]>    ();

  constructor(private weather: WeatherService,
              private el: ElementRef) {
  }

  ngOnInit(): void {
    // convert the `keyup` event into an observable stream
    var observable =
    Observable.fromEvent(this.el.nativeElement, 'keyup');
    observable
      .map((e: any) => e.target.value) // extract the value of the input
      .filter((text: string) => text.length > 1) // filter out if empty
      .debounceTime(250)                         // only once every 250ms
      .do(() => this.loading.next(true))         // enable loading
      // search, discarding old events if new input comes in
      .map((query: string) => this.weather.search(query))
      .switch()
      // act on the return of the search
      .subscribe(
        (results: SearchResult[]) => { // on sucesss
          this.loading.next(false);
          this.results.next(results);
        },
        (err: any) => { // on error
          console.log(err);
          this.loading.next(false);
        },
        () => { // on completion
          this.loading.next(false);
        }
      );

  }
}



@Component({
  inputs: ['result'],
  selector: 'search-result',
  template: `
   <div class="col-sm-6 col-md-3">
      <div class="thumbnail">
        <img src="{{result.thumbnailUrl}}">
        <div class="caption">
          <h3>{{result}}</h3>
          <p>{{result}}</p>
          <p><a href="{{result.videoUrl}}"
                class="btn btn-default" role="button">Watch</a></p>
        </div>
      </div>
    </div>
  `
})
export class SearchResultComponent {
  result: SearchResult;
}

@Component({
  selector: 'weather-search',
  template: `
  <div class='container'>
      <div class="page-header">
        <h1>Weather Search</h1>
      </div>
      <div class="row">
        <div class="input-group input-group-lg col-md-12">
          <search-box
             (loading)="loading = $event"
             (results)="updateResults($event)"
              ></search-box>
        </div>
      </div>
      <div class="row">
        <search-result
          *ngFor="let result of results"
          [result]="result">
        </search-result>
      </div>
  </div>
  `
})
export class WeatherSearchComponent {
  results: SearchResult[];

  updateResults(results: SearchResult[]): void {
    this.results = results;
    // console.log("results:", this.results); // uncomment to take a look
  }
}

这是我从api电话中听到的:

/*
       {"coord":{"lon":18.65,"lat":54.35},
       "weather":[{"id":801,"main":"Clouds",
       "description":"few clouds","icon":"02n"}],"base":"stations",
       "main":{"temp":270.15,"pressure":1035,"humidity":92,
       "temp_min":270.15,"temp_max":270.15},"visibility":10000,
       "wind":{"speed":2.1,"deg":290},"clouds":{"all":20},
       "dt":1484665200,
       "sys":{"type":1,"id":5349,"message":0.0029,
       "country":"PL","sunrise":1484636080,"sunset":1484665040},"
       id":3099434,"name":"Gdansk","cod":200}
      */

1 个答案:

答案 0 :(得分:1)

从您的问题中不清楚您是否尝试.map()变量或观察变量。

场景#1:variable.map()

variable必须是数组。从您的代码看,您的变量包含一个对象。

const jsonData = {
  "coord":{"lon":18.65,"lat":54.35},
  // Abridged for brevity...
  id":3099434,"name":"Gdansk","cod":200
};
jsonData.map(...);  // WON'T WORK - `jsonData` must be an array

场景#2:observable.map()

在映射之前,您必须在代码中导入map运算符:

import 'rxjs/add/operator/map';

// Then, later
Observable.map(...);