Angular factory:在上传过程中使用进度更新作用域

Angular factory: update scope with progress during upload

本文关键字:更新 作用域 过程中 factory Angular      更新时间:2023-09-26

我已经写了一个Angular工厂来处理上传到S3:

'use strict';
angular.module('myApp.s3', [])
    .factory('S3', function ($q) {
        var aws = { ... }
        var progress = 0;
        function getFileName(fileURI) {
            return fileURI.split('/').pop();
        }
        return {
            progress: progress,
            upload: function (fileKey, fileURI, mimeType) {
                var fileName = getFileName(fileURI);
                if (fileName === '') {
                    console.log('File name can''t be empty');
                    return;
                }
                var defer = $q.defer();
                defer.promise.then(function (event) {
                    alert(JSON.stringify(event));
                    console.log(event);
                }, function (error) {
                    alert(JSON.stringify(error));
                    console.log(error);
                });
                var fileTransfer = new FileTransfer();
                var fileUploadOptions = new FileUploadOptions();
                fileUploadOptions.fileKey = 'file';
                fileUploadOptions.fileName = fileName;
                fileUploadOptions.chunkedMode = false;
                fileUploadOptions.params = {
                    'key': fileKey,
                    'AWSAccessKeyId': aws.access_key_id,
                    'acl': aws.acl,
                    'policy': aws.policy,
                    'signature': aws.signature
                };
                fileTransfer.upload(fileURI, encodeURI('https://' + aws.bucket + '.s3.amazonaws.com/'),
                    defer.resolve, defer.reject, fileUploadOptions);
                fileTransfer.onprogress = function (progressEvent) {
                    if (progressEvent.lengthComputable) {
                        progress = (progressEvent.loaded / progressEvent.total) * 100;
                        console.log(progress);
                    } else {
                        //loadingStatus.increment();
                    }
                };
                return defer.promise();
            }
        };
    });

这段代码运行良好,文件被上传到S3。进度日志也在工作。当我在控制器中使用此工厂并将进度绑定到作用域时,我不会在作用域中看到进度更新。我猜这是因为作用域没有得到更新事件。

我看到过一个解决方案,其中工厂用范围初始化,并在工厂内调用scope.apply()。我不认为这是在Angular中做这件事的正确方法,但我也不知道正确的方法。任何建议吗?

@Dmitry Tolmachov的回答肯定会起作用,但我会使用延迟。通知,因为您已经使用了承诺,并且因为使用通知您不需要手动调用摘要循环:

fileTransfer.onprogress = function (progressEvent) {
    if (progressEvent.lengthComputable) {
        progress = (progressEvent.loaded / progressEvent.total) * 100;
        console.log(progress);
        defer.notify(progress);
    } else {
        //loadingStatus.increment();
    }
};

然后在控制器中使用。then(success,error,notify)

cf: Angularjs HTTP service POST progress event

这里的问题是,当fileTransfer。调用Onprogress时,它不会启动消化循环。我强烈推荐阅读这篇文章:http://www.sitepoint.com/understanding-angulars-apply-digest/

对于解决方案,一个简单的方法是:

1)向factory注入$rootScope:

.factory('S3', function ($q, $rootScope) {

2)手动启动消化循环:

progress = (progressEvent.loaded / progressEvent.total) * 100;
                    console.log(progress);
$rootScope.$digest();