组件从observable接收数据但视图不更新

时间:2017-09-24 19:20:15

标签: angular ionic-framework

我正在使用离子和角度构建移动应用。我创建了一个委托下载文件的服务。在下载文件时,此服务会创建我的组件观察到的可观察对象。组件按预期接收事件,我可以在控制台中看到数据,但模板视图在下载完成之前不会更新。奇怪的是,如果我尝试切换应用程序菜单,视图会获得更新。

以下是相关代码:

SERVICE

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来自控制台,而#34; doSync&#34;正在运行:

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 

查看

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

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

1 个答案:

答案 0 :(得分: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);
    });