2017-05-13 3 views
2

私は現在、画面に国立公園を表示するIonicアプリのチュートリアルに従っています。データはローカルファイルに格納され、プロバイダによってロードされますが、プロバイダはデータを2回ロードします。 app.component.tsで起動時にデータをロードし、ページがロードされると(park-list.ts)、既にロードされたデータを取得するだけですが、プロバイダはload()メソッドのif-conditionを取得してもデータを2回ロードします。公園-data.tsプロバイダがデータを2回ロードするのはなぜですか?

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

setTimoutファンクションにthis.parkData.getParkData().then(data => this.parks = data);を入力すると、プロバイダはデータを1回だけ「ダウンロード」します。 parkData.load()parkData.getParkData()が次々に呼び出され、私のプロバイダのdataプロパティがnullのままだからですか? この問題で私を助けてくれることを願っています。

+1

注意を。 'if(this.data){'は、* started *を持っているかどうかではなく、別の呼び出しが*成功したかどうかだけを伝えます。 – jonrsharpe

+0

サービスにデータがロード(キャッシュ)されるようにするには、サービスコンストラクタで 'load'を呼び出すのはなぜですか?また、htmlのこのコンポーネント 'page-park-list'は2回ですか? –

+0

あなたは 'skipUntil()'オペレータ – Aravind

答えて

0

あなたはデータをキャッシュしていますが、約束ではありません。これはよくある間違いです。

あなたのコードは、データの2つの要求(データを受信する前)が受信でき、2つの異なるhttp要求をトリガする競合状態の影響を受けやすいです。

  • load()が呼び出され、this.dataが設定されていないと、約束が作成されます。
  • load()が再度呼び出され、this.dataが設定されていないと、約束が作成されます。
  • 最初の約束の解決、設定this.data
  • 第2約束の解決、再度設定this.data

あなたは約束していないデータキャッシュすることにより、この問題を解決することができます:*あなたは少しfaff、あるいは単に*使用の観測との約束に観測を変換するには、 `toPromise`を使用することができます

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

} 
関連する問題