情况如下:用户可以在应用程序中上传文件。他们可以随时(和次数)这样做。
我想在完成任何上传时显示一个微调器,并在当前没有上传时将其删除。
上传是外部文件上传插件(如blueimp)的处理,在它的添加方法上我抓住jqXHR对象并将它们添加到主干集合(这是我的应用程序中的图像,所以我将它与Marionette的组合使用collectionviews)。
以下是在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 :(得分: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);
}
});
然后setUploading方法应该设置为true,clearUploading应该将其更改为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();
}
我相信当你在其中保存模型时,也会在集合上触发'sync'和'request'事件。因此,您仍然可以在视图中收听集合上的请求,同步和错误事件。