2017-01-26 2 views
2

Ich kann meine Funktion (in einem Dienst) nicht für eine http get Anfrage verwenden, aber wenn ich meine Funktion in meiner Komponente direkt verwende, funktioniert es. Ich verwende eine PHP-Datei, die einen JSON zurückgibt.Angular2 Http bekommen Anfrage mit Service

Ich erhalte diesen Fehler

"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)" 

Es ist nicht

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(); 
    }); 
} 

Dienst

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()); 
    } 
} 

Komponente funktioniertPHP

<?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); 
?> 

Es funktioniert

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()); 
    }); 
} 
} 
+1

werden Sie die ShoeService bieten? – chrispy

Antwort

5

In Ihrer Komponente Sie den Service anrufen, die eine beobachtbare zurück, aber sie zuweisen, dass beobachtbare direkt auf Ihre Daten stattdessen auf die Ergebnisse der abonnieren möchte.

Es sollte

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

Und in Ihrem Service sollten Sie Karte statt abonnieren anrufen, damit Sie die Daten zurückgeben und nicht die HttpResult.

Beachten Sie, dass Sie, um eine bessere Typenunterstützung zu bieten, definieren sollten, was es Ihre Methoden zurückgeben. Beispiel: getData(): Observable<any> und noch besser wäre, wenn Sie any mit einem Schnittstellentyp ersetzen, den Sie definieren, oder Sammlung/Array von Schnittstelle, wenn es eine Sammlung ist.

Beispiel

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

Service-Methode

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

Ow danke! Es klappt ! ☺ –

1

Sie auf Kartendaten sollten eine Antwort Objekt wie unten

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'); 
    } 
} 

und Ihre ngOnInit sollte wie

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

, ändern Sie die Art Ihrer Daten in Ihrem ShoeDetailComponent als

data : any[] 
Verwandte Themen