typescript - Angular 2 http get observable kallas två gånger
I Angular 2 v2.0.1 kallas onInit två gånger. (Självklart gör jag också något fel när det kallas en gång, men det är inte problemet just nu)
Här är min Plunker: http://plnkr.co/edit/SqAiY3j7ZDlFc8q3I212?p=preview
Här är servicekoden:
import {Injectable} from '@angular/core';
import {Http, Response} from '@angular/http';
import {Observable} from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';
@Injectable()
export class DemoService {
constructor(private http:Http) { }
// Uses http.get() to load a single JSON file
getData() {
return this.http.get('./src/data.json')
.map((res:Response) => res.json())
.do(data => console.log(data))
.subscribe(data => {
return <PageContent[]>data;
}, error => console.log("there was an error!"));
}
}
export class PageContent {
constructor(public _id: string,
public tag: string,
public title: string,
public body?:string,
public image?: string) {}
}
... och den enkla komponenten som använder den.
//our root app component
import {Component, NgModule, OnInit } from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import { DemoService, PageContent } from './service';
import { HttpModule } from '@angular/http';
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
</div>
<div *ngFor="let page of pages">
{{ page.title }}
</div>
`
})
export class App implements OnInit {
name:string;
pages: PageContent[] = [];
constructor(private _service: DemoService) {
this.name = 'Angular2'
this.loadData(); // <-- this is called once
}
ngOnInit() {
//this.loadData(); // <-- this is called twice
}
loadData(){
this.pages = this._service.getData();
console.log(this.pages);
}
}
@NgModule({
imports: [ BrowserModule, HttpModule ],
declarations: [ App ],
providers: [DemoService],
bootstrap: [ App ]
})
export class AppModule {}
Ansvarsfriskrivning: det blir ett fel, men du kan se att det serveras en gång när servicemetoden anropas från konstruktorn, men den anropas två gånger när den är inuti ngOnInit-hooken.
Min fråga är, varför kallas det två gånger från OnInit-funktionen?
UPPDATERING: lösning från alla svar:
Det här är den nya servicemetoden:
getData() {
return this.http.get('./src/data.json')
.map((res:Response) => res.json() as PageContent[]);
}
... och detta är den nya komponentmetoden:
loadData(){
this._service.getData()
.subscribe(data => this.pages = data);
}
Svar #1
Din subscribe bör placeras i komponenten istället för i tjänsten. Anledningen är att din komponent är prenumererad på de data som returneras från tjänsten, och senare kan du avprenumerera eller lägga till mer kontroll (som debouncing) om det behövs. Koden kommer att se ut så här efter ändringarna.
I din komponent:
ngOnInit() {
this.loadData();
}
loadData(){
this._service.getData().subscribe(data => this.pages = data);
}
Till din tjänst:
getData() {
return this.http.get('./src/data.json')
.map((res:Response) => res.json());
}
Svar #2
this._service.getData() returnerar ett Subject, inte en lista med PageContent. Du kan ändra din loadData så här:
loadData() {
this._service.getData().subscribe(data => this.pages = data);
console.log("Load data !");
}
och ta bort subscribe-delen av din getData-metod (från DemoService). Jag har precis testat detta, och ngOnInit kallas en gång
