简体   繁体   中英

ionic2 service data rention

I have the following service class, its been set as singleton in providers etc.

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import { Geolocation } from 'ionic-native';
import { Platform } from 'ionic-angular';

import 'rxjs/Rx';

@Injectable()
export class TestService {
private appData: any;
constructor(private http: Http) {
    console.log("service constructor called");
    this.loadAppData();
}

loadAppData() {
    let url = `/api/b502daab-2c7b-4cea-a00e-dc5aa6b58196`;
    this.http.get(url).map(res => res.json()).subscribe(data => {
        this.appData = data;
        console.log(this.appData);
    });
    console.log(this.appData);
}
getAppData()
{
    return this.appData;
}

}

The console.log(this.appData) inside the subscribe outputs an object as it should the one after outputs undefined, shouldnt it be set by then? to make the matters worse.

I am calling the loadappdata on constructor and in my pages i want to get the object by calling

export class HomePage {

constructor(public navCtrl: NavController, public testService: TestService) {
console.log(testService.getAppData());
};


}

but getAppData is always undefined,

I am trying to have a service retain an object so my pages can get data from this as they need. I was under the impression that thats how one should utilize service to share data across pages

You are facing those issues because of the asyncronous ajax request of the http.get call. The programm order in this.loadAppData function is as follows: First you do the ajax request this.http.get

Next you console.log outside the subscribe

Once the response of the get request receives the response the arrow function of subscribe will be called and you console.log again.

The solution is to return the http.get Observable from the service and subscribe to it in your component.

@Injectable()
export class TestService {
constructor(private http: Http) {}

loadAppData() {
    let url = `/api/b502daab-2c7b-4cea-a00e-dc5aa6b58196`;
    return this.http.get(url).map(res => res.json());
}


export class HomePage {
    constructor(public navCtrl: NavController, public testService: TestService) {
        this.testService.loadAppData().subscribe(data => {
            this.appData = data;
        });
    };
}

To cache your data you could return a Promise that resolves to locally cached data or if not available requests and returns. For example:

@Injectable()
export class TestService {

    public data: any;

    constructor(private http: Http) {}

    loadAppData() {

        return new Promise((resolve) => {
            if (this.data) {
                return resolve(this.data);
            } else {
                let url = `/api/b502daab-2c7b-4cea-a00e-dc5aa6b58196`;
                return this.http.get(url)
                    .map(res => res.json())
                    .subscribe(data => {
                        this.data = data;
                        return resolve(data);
                    });
            }
       });
}

1 - You can use ngrx store https://github.com/ngrx/store - to store the service results and each page will retrieve the information from the store.

2- Use ReplaySubject -

In your service code:

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import { Geolocation } from 'ionic-native';
import { Platform } from 'ionic-angular';

import 'rxjs/Rx';

@Injectable()
export class TestService {
private appData: any;
constructor(private http: Http) {
    this.userSubject = new ReplaySubject<any>(1);
this.loadAppData().subscribe(resp => {console.log(resp)});
}

loadAppData():observable<any> {
    let url = `/api/b502daab-2c7b-4cea-a00e-dc5aa6b58196`;
    this.http.get(url).map(res => res.json()).map(data => {
      this.userSubject.next(data);
      return data;
    });
    console.log(this.appData);
}

get appData(): Observable<any> {
    return this.userSubject.asObservable();
  }

In your home page:

export class HomePage {

constructor(public navCtrl: NavController, public testService: TestService) {
console.log(testService.getAppData());
};

ngOninit() {
this.appData.subscribe(resp => {
 console.log(resp)
});

}

in Your Profile page:

export class ProfilePage {

    constructor(public navCtrl: NavController, public testService: TestService) {
    console.log(testService.getAppData());
    };

    ngOninit() {
    this.appData.subscribe(resp => {
     console.log(resp)
    });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM