Javascript 角度工厂:在上载过程中随进度更新范围
我编写了一个Angular factory,它处理到S3的上传:Javascript 角度工厂:在上载过程中随进度更新范围,javascript,angularjs,amazon-s3,angularjs-scope,factory,Javascript,Angularjs,Amazon S3,Angularjs Scope,Factory,我编写了一个Angular factory,它处理到S3的上传: 'use strict'; angular.module('myApp.s3', []) .factory('S3', function ($q) { var aws = { ... } var progress = 0; function getFileName(fileURI) { return fileURI.split('/').pop(
'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()。我不认为这是正确的方法,但我也不知道正确的方法。有什么提示吗?这里的问题是,当调用fileTransfer.onprogress时,它不会启动摘要周期。我强烈推荐阅读本文: 至于解决方案,其中一个简单的方法是: 1) 将$rootScope注入工厂:
.factory('S3', function ($q, $rootScope) {
2) 手动启动摘要周期:
progress = (progressEvent.loaded / progressEvent.total) * 100;
console.log(progress);
$rootScope.$digest();
这必须解决它。@Dmitry Tolmachov答案肯定会起作用,但我会使用defer.notify,因为您已经在使用承诺,并且因为使用notify,您不需要手动调用摘要周期:
fileTransfer.onprogress = function (progressEvent) {
if (progressEvent.lengthComputable) {
progress = (progressEvent.loaded / progressEvent.total) * 100;
console.log(progress);
defer.notify(progress);
} else {
//loadingStatus.increment();
}
};
然后在你的控制器中使用它。然后(成功、错误、通知)
cf:谢谢!这就像预期的一样!但是我不应该调用$apply()吗?在您提供的文章中,只显式调用了$apply()函数。对于rootScope,查看scope.apply的官方文档并不重要,您将看到:函数$apply(expr){try{return$eval(expr);}catch(e){$exceptionHandler(e);}最终{$root.$digest()}所以$rootScope.$digest仍然被调用,但是$apply的目的是为普通$scope运行一些代码并在它之后运行摘要,但是这确实很重要,因为$scope.$digest()只会为这个$scope更新视图并运行观察程序。运行$scope时,$apply()会将整个应用程序更新为通常是!我刚刚发现这是可能的,我认为这是更好的!谢谢