2015-09-04 67 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()將像往常一樣更新整個應用程序 –