angular 2 observable.subscribe is not executed until being called a second time

时间:2016-10-20 19:00:11

标签: angularjs angular2-services angular2-observables

I am trying to have this component get string data from a service that returns an observable

import { Component, OnInit, OnDestroy } from '@angular/core';
import { TabFourService } from "./tabfour.service";
import { Subscription } from "rxjs";

@Component({
    selector: 'tab-four',
    template: `
                {{title}}
              `
})

export class TabFourComponent implements OnInit, OnDestroy{
    title: string = "This is Tab four";

    subscription: Subscription;

    constructor(private tabfourService: TabFourService){}

    ngOnInit(){
        console.log("now in init");
        this.getItems();
        this.getItems();
    }

    getItems(){
        console.log("now in get items");
        this.subscription = this.tabfourService.getItems()
                                .subscribe(data => console.log("testing observable"));
    }

    ngOnDestroy() {
        this.subscription.unsubscribe();
    }
}

Here is a simple service:

import { Injectable } from '@angular/core';
import { Subject }    from 'rxjs/Subject';
import { Observable } from "rxjs";

@Injectable()
export class TabFourService {
    items: string;

    private itemSource = new Subject<string>();

    constructor(){}

    itemSource$ = this.itemSource.asObservable();

    getItems(): Observable<string> {
        this.itemSource.next("aaa");
        return this.itemSource$;
    }

}

I list the service as a provider in @NgModule() so that it can be shared by all component instances. There is also a router for TabFourComponent so every time I navigate to it I should see "testing observable" in the console. But it didn't show until I called getItems() twice. I wonder why it didn't get triggered at the first time.

tabfour.component.ts:20  now in init
tabfour.component.ts:26  now in get items
tabfour.component.ts:26  now in get items
tabfour.component.ts:28  testing observable

Edit:

While in another case where services provide data from http.get

// in service
getLibraryFromDatabase(): Observable<any[]> {
  return this.http.get(<some url>)
             .map(data => data.json())
             .catch(this.handleError);
}

Component doesn't need to call service's method again after subscription.

// in component
ngOnInit() {
    this.subscription = this.libraryService.getLibraryFromDatabase()
                        .subscribe(libs => this.createLibs(libs));
}

1 个答案:

答案 0 :(得分:1)

If the subscribed method is not called until the second getItems() execution, it's because the event is triggered BEFORE the subscription is taken in charge. Register the subscription in the ngOnInit method, (that's the best place to do this kind of things) and then call the method that triggers the event that you have subscribed to:

ngOnInit() {
    this.subscription = this.tabfourService.getItems()
                            .subscribe(data => console.log("testing observable"));
    // The subscription has been taken in charge, now call the service's method
    this.tabFourService.getItems();
}