我目前正在关注一个在屏幕上显示国家公园的Ionic应用程序的教程。数据存储在本地文件中,由我的Provider加载,但Provider加载数据两次。我想在app.component.ts
启动时加载数据,然后当页面加载(park-list.ts
)时,它应该只获取已经加载的数据,但是提供程序加载数据两次,即使我得到了一个if我的load()
方法中的条件。 (它记录“下载”两次)
提供者:park-data.ts
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
@Injectable()
export class ParkData {
data: any = null;
constructor(public http: Http) {
console.log('Hello ParkData Provider');
}
load() {
if (this.data) {
return Promise.resolve(this.data);
}
return new Promise((resolve) => {
this.http.get("assets/data/data.json")
.map(res => res.json())
.subscribe(data => {
console.log("DOWNLOADING");
this.data = data;
resolve(this.data);
})
});
}
getParkData() {
return this.load().then((data) => { return data });
}
}
app.component.ts
import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import { TabsPage } from '../pages/tabs/tabs';
import { ParkData } from "../providers/park-data";
@Component({
templateUrl: 'app.html',
providers: [ParkData]
})
export class MyApp {
rootPage = TabsPage;
constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen, public parkData: ParkData) {
console.log(parkData);
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
statusBar.styleDefault();
splashScreen.hide();
});
this.parkData.load();
}
公园list.ts
import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { ParkData } from "../../providers/park-data";
import { ParkDetails } from "../park-details/park-details";
@Component({
selector: 'page-park-list',
templateUrl: 'park-list.html'
})
export class ParkListPage {
parks: Array<Object> = [];
constructor(public navCtrl: NavController, public navParams: NavParams, public parkData: ParkData) {
this.parkData.getParkData().then(data => this.parks = data);
}
ionViewDidLoad() {
console.log('ionViewDidLoad ParkListPage');
}
openParkDetails(park): void {
this.navCtrl.push(ParkDetails, {parkData: park});
}
}
当我将this.parkData.getParkData().then(data => this.parks = data);
放入setTimout
函数时,我的提供商只会“下载”一次数据。是因为parkData.load()
和parkData.getParkData()
被一个接一个地调用得如此之快,以至于我的提供商中的data
属性保持null
?
我希望你能帮我解决这个问题。
答案 0 :(得分:0)
你正在缓存数据而不是承诺 - 这是一个非常常见的错误。
您的代码容易受到竞争条件的影响,在这种情况下,可以接收两个数据请求(在接收数据之前) - 并触发两个不同的http请求。
load()
,未设置this.data
,创建承诺。load()
,未设置this.data
,创建了承诺。this.data
this.data
。您可以通过缓存承诺而非数据来解决此问题:
export class ParkData {
data: Promise<any> = null;
constructor(public http: Http) {
console.log('Hello ParkData Provider');
}
load() {
if (this.data) {
return this.data;
}
return this.data = this.http.get("/assets/data/data.json").toPromise();
}
getParkData() {
return this.load().then((data) => { return data });
}
}