2013-11-28 39 views
0

上下文

情況如下:用戶可以在應用程序中上傳文件。他們可以隨時(以及多次)完成此操作。檢查例如文件上傳的動態延遲量

我想在任何上傳完成時顯示一個微調,並在當前沒有上傳時刪除它。

我的做法

的上傳是由一個外部文件上傳插件(如blueimp)句柄和它的Add方法我搶jqXHR對象並將其添加到骨幹集合(這是在我的應用程序的圖像,所以我將它與Marionette的收藏視圖結合使用)。

下面是一個叫木偶ItemView控件的OnRender將回調函數的一部分:

// Get the file collection 
var uploadFiles = SomeBackBoneCollection; 

// Track how many deferreds are expected to finish 
var expected = 0; 

// When an image is added, get the jqXHR object 
uploadFiles.bind('add', function(model) { 
    // Get jqXHR object and call function which tracks it 
    trackUploads(model.get('jqXHR')); 

    // Do something to show the spinner 
    console.log('start the spinner!'); 

    // Track amount of active deferreds 
    expected++; 
}, this); 

// Track the uploads 
function trackUploads(jqXHR) { 
    $.when(jqXHR).done(function(){ 
     // A deferred has resolved, subtract it 
     expected--; 

     // If we have no more active requests, remove the spinner 
     if (expected === 0) { 
      console.log('disable the spinner!'); 
     } 
    }); 
} 

討論

此方法效果非常好,但我不知道是否有任何其他(更好)的方法。

您對這種方法有什麼看法?關於這種方法,您是否看到任何上升或下降?任何其他方法或建議任何人?

例如,擁有某種你可以繼續傳遞延遲的數組/對象可能會很好,並且$ .when會以某種方式監視這個集合並解決在任何時候一切都完成的情況。但是,這應該起作用,以便您可以在任何給定時間繼續傳遞延遲對象。

回答

0

你可以通過事件做到這一點。

我假設每個文件都是這種模式的一個實例:

App.Models.File = Backbone.Model.extend({}); 

用戶之前上傳的文件,你實際上是在創建一個新的模型,並進行保存。

uploadedFiles.create(new App.Models.File({...})); 

所以在上傳景色...

//listen to collection events 
initialize: function() { 
    //'request' is triggered when an ajax request is sent 
    this.listenTo(this.collection, 'request', this.renderSpinner); 
    //when the model is saved, sync will be triggered 
    this.listenTo(this.collection, 'sync', this.handleCollectionSync); 
} 

renderSpinner: function() { 
    //show the spinner if it is not already being shown. 
} 

行,所以,在 'handleCollectionSync' 功能,你要決定,如果我們想隱藏的微調。 那麼我們如何知道是否還有模型正在上傳?你檢查是否有是集合(未保存的模型)

所以您的收藏在新車型中,添加一個輔助方法:

App.Collections.Files = Backbone.Collection.extend({ 

    //if there's a new model, return true 
    hasUnsavedModels: function() { 
    return this.filter(function(model) { 
     return model.isNew(); 
    }).length > 0; 
    } 
}); 

回到你的觀點:

handleCollectionSync: function() { 
    //if there's no unsaved models 
    if(!this.collection.hasUnsavedModels()){ 
    //removespinner 
    } 
} 

這假設所有上傳都成功,應該解決您的問題。您可能希望在錯誤處理案例中完成此操作 - 取決於您想要對錯誤案例執行的操作,但只要您不馬上重試,就應該將其從集合中刪除。

============================================== ============================================

編輯

我在想,如果你允許用戶多次上傳文件,你並不是真的創建新的模型,而是更新現有的模型,所以以前的答案是行不通的。爲了解決這個問題,我會跟蹤模型本身的狀態。

App.Models.File = Backbone.Model.extend({ 
    initialize: function() { 
    this.uploading = false; //default state 
    this.on('request', this.setUploading); 
    this.on('sync error', this.clearUploading); 
    } 
}); 

then setUploading method should set uploading to true,clearUploading should change it to false;

,並在您的收藏:

hasUnsavedModels: function() { 
    return this.filter(function(model) { 
    return model.uploading; 
    }).length > 0; 
} 

所以在你看來,當你創建一個新的文件

uploadNewFile: function(fileAttributes) { 
    var newFile = new App.Model.File(fileAttributes); 
    this.collection.add(newFile); 
    newFile.save(); 
} 

我相信「同步」和「請求」事件引發了收集太當你將模型保存在其中時。因此您仍然可以在視圖中偵聽集合上的請求,同步和錯誤事件。

+0

雖然這是很好的方法,但它讓我覺得!這與我的情況並不完全相同,因爲上傳正由(任何)fileuploader插件處理。我從來沒有保存模型,因爲我不需要。我只是通過這種方法跟蹤圖像上傳進度。但是,也許使用保存(並上傳)模型也是一個好方法。在這種情況下,我認爲我只需要一個文件輸入按鈕而不是整個插件;上傳在保存模型中完成。 –

+0

澄清了問題中的一點差異。 –

+0

編輯我的答案更詳細(和另一種方法)。既然你已經在使用集合,爲什麼不使用模型呢?順便說一句,在您的原始方法中,將jqXHR附加到模型不會是一個問題,除非您獲得太多模型...因爲現在所有jqXHR都有它的參考(它的模型),它們將永遠不會被垃圾收集,直到您移除內存中的模型。 –