2015-09-04 78 views
2

期间更新与进步的范围,我写了一个角的工厂,负责处理上传到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中这样做的正确方法,但我也不知道正确的方式。有小费吗?

回答

2

@Dmitry Tolmachov答案将definitly工作,但因为你已经在使用一个承诺,我会用defer.notify因为使用通知你不需要手动调用摘要周期:

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

然后用它在你的CONTROLER进行。于是(sucess,错误通知)

CF:Angularjs HTTP service POST progress event

+0

是的!我刚发现这是可能的,我认为它更好!谢谢! –

1

这里的问题是,当调用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(); 

这必须解决它。

+0

谢谢!这按预期工作!但是,我不应该调用$ apply()来代替?在您提供的文章中,只显式调用$ apply()函数。 –

+0

对于rootScope,如果您查看scope.apply的官方文档,则无关紧要。您将看到: 函数$ apply(expr){ try { return $ eval(expr);捕获(e){ $ exceptionHandler(e); } finally { $ root。$ digest(); } } So $ root digest被调用,但$ apply的目的是运行一些代码并在它后面运行摘要 –

+0

对于普通的$ scope,但它确实很重要,因为$ scope。$ digest()会更新视图并只为这个$范围运行观察者。当运行$ scope。$ apply()将像往常一样更新整个应用程序 –