【问题标题】:Angular factory: update scope with progress during upload角工厂:在上传过程中更新范围与进度
【发布时间】:2015-11-30 08:18:23
【问题描述】:

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

'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 中执行此操作的正确方法,但我也不知道正确的方法。有什么建议吗?

【问题讨论】:

    标签: javascript angularjs amazon-s3 angularjs-scope factory


    【解决方案1】:

    @Dmitry Tolmachov 的回答肯定会起作用,但我会使用 defer.notify ,因为您已经在使用 Promise 并且因为使用通知您不需要手动调用摘要循环:

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

    然后在你的控制器中使用它是 .then(sucess,error,notify)

    cf : Angularjs HTTP service POST progress event

    【讨论】:

    • 是的!我刚刚发现这是可能的,我认为它甚至更好!谢谢!
    【解决方案2】:

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

    至于解决方案,其中一种简单的方法是:

    1) 将 $rootScope 注入工厂:

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

    2) 手动启动摘要循环:

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

    这必须解决它。

    【讨论】:

    • 谢谢!这按预期工作!但是我不应该改为调用 $apply() 吗?在您提供的文章中,仅显式调用了 $apply() 函数。
    • 对于 rootScope 来说,查看 scope.apply 的官方文档并不重要,您会看到: function $apply(expr) { try { return $eval(expr); } 捕捉 (e) { $exceptionHandler(e); } 最后 { $root.$digest();所以无论如何都会调用$rootScope.$digest,但是$apply的目的是运行一些代码并在它之后运行digest
    • 对于普通的 $scope 但它确实很重要,因为 $scope.$digest() 将只为这个 $scope 更新视图和运行观察者。运行时 $scope.$apply() 将照常更新整个应用程序
    猜你喜欢
    • 2015-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多