【问题标题】:Checking dynamic amount of deferreds of for example file uploads检查例如文件上传的动态延迟量
【发布时间】:2013-11-28 20:53:26
【问题描述】:

上下文

情况如下:用户可以在应用程序中上传文件。他们可以在任何时间(以及多次)这样做。

我想在上传完成时显示一个微调器,并在目前没有上传时将其删除。

我的方法

上传是由外部文件上传插件(如 blueimp)处理的,在它的 add 方法上,我抓取 jqXHR 对象并将它们添加到主干集合(它们是我的应用程序中的图像,所以我将它与 Marionette 结合使用集合视图)。

以下是 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 以某种方式监控此集合并在任何时候解决所有问题。但是,这应该可以让您在任何给定时间继续传递延迟对象。

【问题讨论】:

    标签: backbone.js marionette jquery-deferred


    【解决方案1】:

    您可以通过事件来做到这一点。

    我假设每个文件都是这个模型的一个实例:

    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方法应该把uploading设置为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();
    }
    

    我相信当您在其中保存模型时,也会在集合上触发“同步”和“请求”事件。所以你仍然可以在视图中监听集合上的请求、同步和错误事件。

    【讨论】:

    • 虽然这是一个不错的方法,但它让我思考!从某种意义上说,上传由(任何)fileuploader插件处理,这与我的情况并不完全相同。我从不保存模型本身,因为我不必这样做。我只是通过这种方法跟踪图像上传进度。但是,也许使用保存(并因此上传)的模型也是一个好方法。在那种情况下,我认为我只需要一个文件输入按钮而不是整个插件;上传是在模型的保存中完成的。
    • 澄清了问题中的差异。
    • 用更多细节(和另一种方法)编辑了我的答案。既然您已经在使用集合,为什么不使用模型呢?顺便说一句,在你原来的方法中,在你得到太多模型之前,将 jqXHR 附加到模型上不是问题......因为现在所有 jqXHR 都有对它的引用(它的模型),它们永远不会被垃圾收集,直到你删除你的记忆中的模型。
    • 另一个问题是......你有一个状态(var expected = 0;)被两个不同范围内的两个函数操作。从长远来看,这可能会导致问题,并使您的应用程序更难维护。 (试图在一个函数中修复某些问题的人必须确保“预期”在其他函数中仍然有效,并且他还必须找到所有使用相同变量的地方!)
    • 关于垃圾回收,这是一个好点!如果 jqXHR 对象解决后我删除它怎么办?关于状态变量,您有一个很好的观点,如果我要使用这种方法,对这种特殊情况有什么建议吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-22
    • 1970-01-01
    • 1970-01-01
    • 2020-11-22
    相关资源
    最近更新 更多