【问题标题】:ionic2 service data rentionionic2 服务数据保留
【发布时间】:2017-01-25 05:28:39
【问题描述】:

我有以下服务类,它在提供者等中设置为单例。

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

}

订阅中的console.log(this.appData) 输出一个对象,因为它应该在输出未定义之后的那个对象,不应该在那时设置吗?让事情变得更糟。

我在构造函数上调用 loadappdata,在我的页面中我想通过调用来获取对象

export class HomePage {

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


}

但 getAppData 始终未定义,

我正在尝试让服务保留一个对象,以便我的页面可以根据需要从中获取数据。我的印象是应该如何利用服务跨页面共享数据

【问题讨论】:

    标签: angular ionic-framework


    【解决方案1】:

    1 - 您可以使用ngrx store https://github.com/ngrx/store - 来存储服务结果,每个页面都会从存储中检索信息。

    2- 使用ReplaySubject -

    在您的服务代码中:

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

    在您的主页中:

    export class HomePage {
    
    constructor(public navCtrl: NavController, public testService: TestService) {
    console.log(testService.getAppData());
    };
    
    ngOninit() {
    this.appData.subscribe(resp => {
     console.log(resp)
    });
    

    }

    在您的个人资料页面中:

    export class ProfilePage {
    
        constructor(public navCtrl: NavController, public testService: TestService) {
        console.log(testService.getAppData());
        };
    
        ngOninit() {
        this.appData.subscribe(resp => {
         console.log(resp)
        });
    }
    

    【讨论】:

    • 我不能只将我得到的对象存储在一个全局中而不是使用一个商店吗?稍后必须存储和检索似乎效率不高。
    【解决方案2】:

    由于 http.get 调用的异步 ajax 请求,您正面临这些问题。 this.loadAppData 函数中的程序顺序如下: 首先你做ajax请求this.http.get

    接下来你在订阅之外的console.log

    一旦get请求的响应收到响应,订阅的箭头函数将被调用,你再次console.log。

    解决方案是从服务中返回 http.get Observable 并在您的组件中订阅它。

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

    要缓存您的数据,您可以返回一个解析为本地缓存数据的 Promise,或者如果不可用,则请求并返回。例如:

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

    【讨论】:

    • 但是如果我从多个页面多次调用 loadAppData 不会多次调用 url 吗?我试图调用一次 loadAppData 并使用其结果,而不必一遍又一遍地调用服务
    • 我添加了一些代码。缺点是您无法控制何时再次重新加载数据。您可以做的是在您的 app.component 中加载数据,就像您在我的第一个示例的主页和订阅成功函数中所做的那样,将数据分配给您在每个页面中访问的 TestService 成员变量,然后分配根页面。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-31
    • 2015-07-17
    • 1970-01-01
    • 2018-05-18
    • 2019-01-07
    • 2023-03-17
    • 2018-10-28
    相关资源
    最近更新 更多