Angular2 Http获取服务请求

时间:2017-01-26 21:44:09

标签: angular

我无法使用我的函数(在服务中)获取http get请求,但如果我直接在我的组件中使用我的函数,它就可以工作。 我使用返回JSON的PHP文件。

我收到此错误

"Uncaught (in promise): TypeError: Cannot set property stack of [object Object] which has only a getter
TypeError: Cannot set property stack of [object Object] which has only a getter
at assignAll (http://localhost:4200/vendor.bundle.js:112997:29)
at ViewWrappedError.ZoneAwareError (http://localhost:4200/vendor.bundle.js:113068:16)
at ViewWrappedError.BaseError [as constructor] (http://localhost:4200/vendor.bundle.js:6624:16)
at ViewWrappedError.WrappedError [as constructor] (http://localhost:4200/vendor.bundle.js:6686:16)
at new ViewWrappedError (http://localhost:4200/vendor.bundle.js:63377:16)
at CompiledTemplate.proxyViewClass.DebugAppView._rethrowWithContext (http://localhost:4200/vendor.bundle.js:90236:23)
at CompiledTemplate.proxyViewClass.DebugAppView.detectChanges (http://localhost:4200/vendor.bundle.js:90209:18)
at ViewRef_.detectChanges (http://localhost:4200/vendor.bundle.js:64323:20)
at RouterOutlet.activate (http://localhost:4200/vendor.bundle.js:74734:42)
at ActivateRoutes.placeComponentIntoOutlet (http://localhost:4200/vendor.bundle.js:25777:16)
at ActivateRoutes.activateRoutes (http://localhost:4200/vendor.bundle.js:25744:26)
at http://localhost:4200/vendor.bundle.js:25680:58
at Array.forEach (native)
at ActivateRoutes.activateChildRoutes (http://localhost:4200/vendor.bundle.js:25680:29)
at ActivateRoutes.activate (http://localhost:4200/vendor.bundle.js:25654:14)"

不起作用

组件

import {Component, OnInit} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {Shoe} from './shoe';
import {FileService} from  './../services/file.service';
import {ShoeService} from  './../services/shoe.service';
import {Observable} from "rxjs";

@Component({
    selector: 'shoe',
    templateUrl: 'shoe-detail.component.html',
    providers: [FileService]
})
export class ShoeDetailComponent implements OnInit {

constructor(private shoeService: ShoeService) {}

data : any;

ngOnInit() {
        this.data = this.shoeService.getData();
    });
}

服务

import { Injectable } from '@angular/core';
import { Shoe } from './../shoe/shoe';
import {Http, Response} from '@angular/http';

@Injectable()
export class ShoeService {

constructor (private http: Http) {}

getData() {
    return this.http.get('http://.../test.php')
        .subscribe(data => data.json());
    }
}

PHP

<?php
header("Access-Control-Allow-Origin: *");
$data = array(
    array('id' => '1','first_name' => 'Cynthia'),
    array('id' => '2','first_name' => 'Keith'),
    array('id' => '3','first_name' => 'Robert'),
    array('id' => '4','first_name' => 'Theresa'),
    array('id' => '5','first_name' => 'Margaret')
);

echo json_encode($data);
?>

有效

import {Component, OnInit} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {Shoe} from './shoe';
import {FileService} from  './../services/file.service';
import {ShoeService} from  './../services/shoe.service';
import {Http, Response} from '@angular/http';

@Component({
    selector: 'shoe',
    templateUrl: 'shoe-detail.component.html',
    providers: [FileService]
})
export class ShoeDetailComponent implements OnInit {

constructor(private fileService: FileService,
            private shoeService: ShoeService,
            private route: ActivatedRoute,
            private http: Http) {
}

data: any;

ngOnInit() {
    this.http.get('http://...test.php')
            .subscribe(data => this.data = data.json());
    });
}
}

2 个答案:

答案 0 :(得分:5)

在您的组件中,您正在调用返回Observable的服务,但您将Observable直接分配给您的数据,而不是订阅其结果。

应该是

ngOnInit() {
    this.shoeService.getData().subscribe(data => this.data = data);
});

在您的服务中,您应该调用map而不是subscribe,这样您就可以返回数据,而不是HttpResult。

getData(): Observable<any> {
    return this.http.get('http://.../test.php')
        .map(data => data.json());
    }
}

请注意,为了提供更好的类型支持,您应该定义方法返回的内容。示例:getData(): Observable<any>,如果将any替换为您定义的接口类型或接口的集合/数组(如果它是集合),则会更好。

实施例

export interface IUser {id: number; first_name: string}

服务方法

getData(): Observable<IUser[]> {
    return this.http.get('http://.../test.php')
        .Map(data => data.json() as IUser[]);
    }
}

答案 1 :(得分:1)

您应该使用响应对象映射到数据,如下所示

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';

import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
@Injectable()

export class ShoeService {
    constructor(private _http: Http) {
    }
    getData(): Observable<any[]> {
        return this._http.get('http://......')
            .map((response: Response) => <any[]>response.json())
            .do(data => console.log("data we got is " + JSON.stringify(data)))
                .catch(this.handleError);

    }
    private handleError(error: Response) {
            console.log(error);
            return Observable.throw(error.json().error || 'Internal Server error');
    }
}

并且你的ngOnInit应该是

ngOnInit() : void{
        this._taskService.getData()
                    .subscribe(data => this.data = data,
                    error =>this.errorMessage =<any> error)
    } 

此外,将ShoeDetailComponent中的数据类型修改为

data : any[]