2017-05-13 37 views
2

我目前在屏幕上顯示國家公園的Ionic應用程序的教程。數據存儲在本地文件中,由我的提供程序加載,但提供程序加載數據兩次。我想在啓動時加載數據app.component.ts,然後當頁面加載時(park-list.ts)它應該只獲取已加載的數據,但提供程序加載數據兩次,即使我在我的load()方法中獲得了if條件。 (它記錄 「正在下載」 兩次)爲什麼我的提供者加載數據兩次?

提供者:公園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? 我希望你能幫助我解決這個問題。

+1

注意,您可以用'toPromise'的可觀轉化爲承諾少一些faff,或者只是*使用觀測* 。還要注意'if(this.data){'只告訴你另一個調用是否成功*,而不是它是否已經啓動*。 – jonrsharpe

+0

如果你想要在服務中加載(緩存)數據,爲什麼不在服務構造函數中調用'load'?此外,html中的這個組件是否是'page-park-list'兩次? –

+0

您可以使用'skipUntil()'運算符 – Aravind

回答

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

} 
相關問題