Angular2服务返回未定义

时间:2017-02-07 16:23:06

标签: javascript json angular typescript angular2-services

由于某些原因,我的服务不起作用。我已经潜伏了两天,试图找到类似的问题,但他们不适合我的问题。

Service.ts:

import { Injectable } from '@angular/core';
import {  Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { CarObject } from './make';

@Injectable()
export class EdmundsService {
  private stylesurl = 'REDACTED';

 constructor(private http: Http) { }

 getCars(): Observable<CarObject[]> {
   return this.http.get(this.stylesurl)
   .map(this.extractData)
   .catch(this.handleError);
  }

  private extractData(res: Response) {
   let body = res.json();
   return body.data || { };
  }
  private handleError (error: Response | any) {
  // In a real world app, we might use a remote logging infrastructure
   let errMsg: string;
   if (error instanceof Response) {
      const body = error.json() || '';
      const err = body.error || JSON.stringify(body);
      errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
     } else {
      errMsg = error.message ? error.message : error.toString();
    }
    console.error(errMsg);
    return Observable.throw(errMsg);
  }

}

这些是我的模特&#39;:

class Style {
  id: number;
  name: string;
  make: Make;
  model: Model;
  year: Year;
  submodel: Submodel;
  trim: string;
  states: string[];
  engine: Engine;
  transmission: Transmission;
  options: Options[];
  colors: Color[];
  drivenWheels: string;
  numOfDoors: string;
  squishVins: string[];
  categories: Categories;
  MPG: MPG;
  manufacturerOptionCode: string;
 }

export class CarObject {
styles: Style[];
stylesCount: number;
}

我的组件:

import { CarObject } from './make';
import { EdmundsService } from './edmunds-search-result.service';

@Component({REDACTED
providers: [EdmundsService] })


export class EdmundsSearchResultComponent implements OnInit {
  cars: CarObject[];
  errorMessage: string;



  constructor(private _edmundsService: EdmundsService) { }

   getCars(): void {
     this._edmundsService.getCars()
     .subscribe(
      cars => this.cars = cars,
      error =>  this.errorMessage = <any>error);
   }


  ngOnInit(): void {
   this.getCars();
  }

}

组件HTML:     {{cars.stylesCount | async}}

示例API响应:http://pastebin.com/0LyZuPGW

错误输出:

EXCEPTION: Error in ./EdmundsSearchResultComponent class 
EdmundsSearchResultComponent - inline template:0:0 caused by: 
Cannot read    property 'stylesCount' of undefined
  1. CarObject旨在匹配API响应,因此可以删除数组括号([])
  2. 我不知道为什么尽管密切关注英雄之旅HTTP /服务教程,但这不会在我的模板上显示对象数据。
  3. 我要做的是从变量&#39; styleurl&#39;做出HTTP请求。 (通过查看chrome dev工具中的“网络”标签,我看到了这一点。)使用此API响应,我希望我的CarObject能够消费&#39; json响应,可用于我的组件/模板。

1 个答案:

答案 0 :(得分:3)

在您的组件中,您保留了car属性,但未对其进行初始化,因此它仍为undefined

当您的HTML呈现承诺尚未完成时,您的car仍然是undefined,但您尝试从中访问该属性。

一对解决方案:

预设

cars: CarObject = new CarObject(); // or <CarObject>{}

在模板中使用elvis运算符

 {{ cars?.stylesCount }}

使用ngIf

 <div *ngIf="cars">{{ cars.styleCount }}</div>

可能有更多方法可以处理这种情况。

请参阅我底部的更新,了解您对async管道的使用情况。它可能会导致您尝试使用它的方式出现错误。

此外,我建议阅读TypeScript类型以及angular和typescript的一般最佳实践,特别是关于模型,接口等的使用。使用Observables也是一个好主意而不是Promises。 您的代码中存在一些问题,所以这只是一个提示,但是我认为这里没有详细说明它们并不是您问题的根源。

希望我能提供帮助。

更新

关于您对async管道的使用情况:

  

异步管道订阅Observable或Promise并返回它发出的最新值。

你在array CarObjects上使用它,btw不应该是一个数组。 看看the documentation for the async pipe for proper usage.