2017-09-24 28 views
0

我正在使用離子和角度構建移動應用程序。我創建了一個服務來委派文件的下載。當一個文件被下載時,這個服務創建一個可觀察到的元素,這個元素被我的組件觀察到。組件按預期接收事件,我可以在控制檯中看到數據,但模板視圖不會更新,直到下載完成。奇怪的是,如果我嘗試切換應用程序菜單視圖獲取更新。組件從observable接收數據但視圖不更新

下面是相關代碼:

服務

import {Injectable} from '@angular/core'; 
import {FileTransfer, FileTransferObject} from "@ionic-native/file-transfer"; 
import {BehaviorSubject} from "rxjs/BehaviorSubject"; 

@Injectable() 
export class DataRetriever { 

    protected fileTransfer: FileTransferObject = this.transfer.create(); 

    protected _progressSource = new BehaviorSubject<number>(0); 

    protected progressStep = 0; 

    progress$ = this._progressSource.asObservable(); 

    /** 
    * Trigger the progress observable 
    * @param {ProgressEvent} progressEvent 
    */ 
    listener(progressEvent:ProgressEvent) { 
     if (progressEvent.lengthComputable) { 
      let progress = Math.round((progressEvent.loaded/progressEvent.total)*100); 
      if(progress > this.progressStep){ 
       console.log("Download progress " + progress + "%"); 
       this.progressStep++; 
       this._progressSource.next(progress); 
      } 
     } else { 
      this._progressSource.next(1); 
     } 
    } 


    /** 
    * Perform sync data download 
    * @returns {Promise<boolean>} 
    */ 
    public doSync() { 
     this.fileTransfer.onProgress((event) => this.listener(event)); 

     return this.getLastUpdate().then(updated_at => { 
      if(updated_at === 0){ 
       let filename = 'first_sync.zip'; 
       return this.downloadFirstSync().then(()=>{ 
        return this.file.checkFile(this.file.dataDirectory,filename); 
       }).then((exists) => { 
        console.log("Success? " + (exists ? "Y" : "N")); 
       }).catch(error=>{ 
        console.log(JSON.stringify(error,null,2)) 
       }); 
      } 
     }); 
    } 


    /** 
    * Download first sync file 
    */ 
    downloadFirstSync() { 

     const url = this.api.getApiURL('first_sync'); 
     let filename = 'first_sync.zip'; 
     return this.fileTransfer 
      .download(url, this.file.dataDirectory + filename,true,Api.getApiHeader(this.token)) 
      .then((entry) => { 
       console.log('Download complete: ' + entry.toURL()); 
       return Promise.resolve(); 
      }).catch(error => { 
       console.log(JSON.stringify(error,null,2)); 
       return Promise.reject(error); 
      }); 
    } 
} 

COMPONENT

import {Component} from '@angular/core'; 
import {DataRetriever} from "../../providers/data-retriever/data-retriever"; 
import {Subscription} from "rxjs/Subscription"; 

@Component({ 
    selector: 'page-data-retrieve', 
    templateUrl: 'data-retrieve.html' 
}) 
export class DataRetrievePage { 

    public updated_at:number = 0; 

    public progressStatus = 0; 

    protected progressSubscription: Subscription; 

    constructor(public navCtrl: NavController, 
       public dataRetriever:DataRetriever) { 
    } 

    ionViewDidLoad() { 

     this.progressSubscription = this.dataRetriever.progress$.subscribe(
      amount => { 
       console.log('Update received ' + amount); 
       this.progressStatus = amount; 
      },error => { 
       console.log(error); 
      }); 

     this.dataRetriever.getLastUpdate().then(result=>{ 
      this.updated_at = result; 
     }); 
     console.log('ionViewDidLoad DataRetrievePage'); 
    } 


    doSync(){ 
     this.dataRetriever.doSync(); 
    } 

    ngOnDestroy() { 
     this.progressSubscription.unsubscribe(); 
    } 
} 

LOG從控制檯而 「doSync」 運行:

Download progress 1% data-retrieve.ts:34 
Update recebido 1 data-retriever.ts:59 
Download progress 2% data-retrieve.ts:34 
Update recebido 2 data-retriever.ts:59 
Download progress 3% data-retrieve.ts:34 
Update recebido 3 data-retriever.ts:59 
Download progress 4% data-retrieve.ts:34 

VIEW

<progress-bar [progress]="progressStatus"></progress-bar> 

<div class="progress-outer"> 
    <div class="progress-inner" [style.width]="progress + '%'"> 
     {{ progress }}% 
    </div> 
</div> 
+2

您是否嘗試過使用異步管道,而不是節省'progressStatus'進展?另一種方法是注入'ChangeDetectorRef'並調用'markForCheck' – Everest

+0

@Everest嗨,謝謝你的消化。我結束了使用ChangeDetectorRef.detectChanges()。 –

回答

0

經過大量的研究和失去了頭髮,我找到了解決方案。

這個問題的主要原因是Angular在需要時監視用戶事件和刷新視圖。如果事件是系統生成的,則視圖不會更新。這就是爲什麼你需要通知角度需要刷新。

所以我下面的代碼添加到我的組件:

this.downloadProgressSubscription = this.dataRetriever.progress$.subscribe(
    (info:ProgressContainer) => { 
     console.log(JSON.stringify(info,null,2)); 
     this.downloadProgress = info; 
     this.ref.detectChanges(); // <- Relevant line 
    },error => { 
     console.log(error); 
    }); 
相關問題