【问题标题】:Wait for the collection to fetch everything in backbone等待集合获取主干中的所有内容
【发布时间】:2012-05-08 01:11:49
【问题描述】:

我有两组收藏。一个用于类别,另一个用于项目。我需要等待类别完成获取所有内容,以便为要获取的项目设置类别。

此外,我每次单击一个类别时都必须重新获取一个新的项目集合,因为每次单击一个类别时都会进行分页,它不会刷新或重新获取集合,因此分页代码搞砸了错误的收藏。有什么想法吗?

this.categoryCollection = new CategoryCollection();
this.categoryCollection.fetch();

this.itemCollection = new ItemCollection();
this.itemCollection.fetch();

【问题讨论】:

    标签: backbone.js


    【解决方案1】:

    刚刚遇到了类似的情况。我最终将 jquery.ajax 参数传递给 fetch() 调用。您可以使第一次获取同步。来自backbone docs

    jQuery.ajax 选项也可以直接作为 fetch 选项传递

    您的代码可以简化为:

    this.categoryCollection.fetch({async:false});
    this.itemCollection.fetch();
    

    【讨论】:

    • 这不是一个好主意,因为它会导致浏览器在等待同步调用完成时锁定。直接来自文档:“请注意,同步请求可能会暂时锁定浏览器,在请求处于活动状态时禁用任何操作。从 jQuery 1.8 开始,不推荐使用 async: false 和 jqXHR ($.Deferred);您必须使用成功/错误/完成回调选项,而不是 jqXHR 对象的相应方法,例如 jqXHR.done() 或已弃用的 jqXHR.success()。" [api.jquery.com/jQuery.ajax/]
    • 使用异步 :false 不是一个好主意。在我看来,当您使用 SPA 时,这毫无意义。
    • 这对我很有用。我试图将 fetch() 与异步一起使用并串联运行进程,但 fetch() 的成功回调在同步完成之前触发。
    • 还应注意,这种方法已被弃用。见帖子:stackoverflow.com/questions/11448011/…
    • 我已经添加了正确的方法stackoverflow.com/a/43427782/1735027
    【解决方案2】:

    一种快速的方法是将回调传递给第一个调用第二个的fetch() 调用。 fetch() 采用支持 success(和 error)回调的 options 对象。

    var self = this;
    this.categoryCollection = new CategoryCollection();
    this.categoryCollection.fetch({
        success: function () {
            self.itemCollection = new ItemCollection();
            self.itemCollection.fetch();
        }
    });
    

    不是最优雅的,但它确实有效。您可能可以使用延迟来做一些创造性的事情,因为fetch() 返回由发生的$.ajax 调用创建的 jQuery 延迟。

    对于分页问题,​​如果不查看您的分页代码在做什么,就很难判断。您将不得不自己滚动分页内容,因为 Backbone 本身不支持它。我可能要做的是为正在查询的页面标准创建一个新的集合,并可能创建一个我可以点击的支持分页的服务器操作(将集合的url 映射到分页服务器操作)。不过,我还没有考虑太多。

    【讨论】:

    【解决方案3】:

    由于那里的答案,我不得不对这个帖子做出反应。

    这是正确的做法!!!

    this.categoryCollection = new CategoryCollection();
    this.itemCollection = new ItemCollection();
    
    var d1 = this.categoryCollection.fetch();
    var d2 = this.itemCollection.fetch();
    
    jQuery.when(d1, d2).done(function () {
         // moment when both collections are populated
         alert('YOUR COLLECTIONS ARE LOADED :)'); 
    });
    

    通过这样做,您可以同时获取两个集合,并且当两者都准备好时您可以拥有事件。因此,您不必等待完成加载第一个集合以获取其他集合,您不会进行 ajax 调用同步等,您可以在其他答案中看到!

    这是Deferred objects 上的文档。

    注意:在本例中,当一个或多个延迟对象失败时,它不会被覆盖。如果您还想在 .done 旁边覆盖这种情况,则必须在 .when 上添加 .fail 回调,并在此示例中添加 error 处理程序,该处理程序将标记失败的 d1 或 d2。

    【讨论】:

    • 不用喊了。
    【解决方案4】:

    我正在使用 RelationalModel 并创建了一个队列提取,它只在加载完成时调用“更改”事件:

    var MySuperClass = Backbone.RelationalModel.extend({
        //...
    
        _fetchQueue : [],
    
        fetchQueueingChange : function(name){
            //Add property to the queue
            this._fetchQueue.push(name);
            var me = this;
    
            //On fetch finished, remove it
            var oncomplete = function(model, response){
                //From _fetchQueue remove 'name'
                var i = me._fetchQueue.indexOf(name);
                me._fetchQueue.splice(i, 1);
    
                //If done, trigger change
                if (me._fetchQueue.length == 0){
                    me.trigger('change');
                }
            };
    
            this.get(name).fetch({
                success: oncomplete, 
                error : oncomplete
            });
        },
    
        //...
    
    
    });
    

    类会调用:

    this.fetchQueueingChange('categories');
    this.fetchQueueingChange('items');
    

    我希望你能改进这一点,它对我很有效。

    【讨论】:

      【解决方案5】:

      我今天遇到了同样的问题并想出了一个解决方案:

      var self = this;
      this.collection = new WineCollection();
      this.collection.url = ApiConfig.winetards.getWineList;
      this.collection.on("reset", function(){self.render()});
      this.collection.fetch({reset: true});
      

      现在,当对集合的提取完成时,会触发“重置”,并在“重置”时调用视图的 render() 方法。

      使用{async: false} 不是处理Backbone 的fetch() 的理想方式。

      【讨论】:

        【解决方案6】:

        只需将 jQuery 设置为同步

        $.ajaxSetup({
          async: false
        });   
        this.categoryCollection.fetch();
        this.itemCollection.fetch();
        $.ajaxSetup({
          async: true
        });
        

        我猜这是最简单的解决方案。当然,在这些 fetch 运行时启动新请求也将以同步方式启动,这可能是您不喜欢的。

        【讨论】:

        • 全局禁用异步调用不是一个好习惯。你可以简单地使用this.categoryCollection.fetch({async:false});
        • 我想知道,如果他包括预防措施,它会被赞成
        猜你喜欢
        • 2013-12-29
        • 1970-01-01
        • 2018-03-18
        • 1970-01-01
        • 1970-01-01
        • 2015-08-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多