代码之家  ›  专栏  ›  技术社区  ›  nice ass

在解析其他多个延迟对象后解析延迟对象

  •  1
  • nice ass  · 技术社区  · 11 年前

    我的经验 $.Deferred 非常有限,到目前为止,代码看起来非常混乱。

    应该返回promise的函数是用ajax请求后收到的HTML更新DOM。

    它是这样使用的:

    this._refreshWorkspace(response.html).then(function(){
      // do things after DOM update finished
    });
    

    以下是功能代码:

    _refreshWorkspace: function(htmlBlocks){
    
      var dfd = $.Deferred();
    
      if('editor' in htmlBlocks){
        app.destroy(this.editor).then((function(){
          this.editor.empty().append(htmlBlocks.editor);
        }).bind(this)).then((function(){
          app.refresh(this.editor);
        }).bind(this));
      }
    
      if('listPanels' in htmlBlocks){
        app.destroy(this.list).then((function(){
          this.list.empty().append(htmlBlocks.listPanels);
        }).bind(this)).then((function(){
          app.refresh(this.list);
          // other unrelated code here
          dfd.resolve();
    
        }).bind(this));
      }
    
      if('listNav' in htmlBlocks){
        // similar code block       
      }
    
      return dfd;
    },
    

    它似乎有效,但前提是提供了“listPanels”htmlBlock。 我想要 dfd 在所有刷新调用后解析一次,或者如果可能的话,在解析所有刷新调用之后解析一次。我怎么才能做到这一点?

    2 回复  |  直到 11 年前
        1
  •  1
  •   T.J. Crowder    11 年前

    将循环中的所有承诺放入数组,然后使用 $.when 。遗憾的是,使用 $.当 使用数组是丑陋的:

    return $.when.apply($, theArray);
    

    因为 $.当 被设计为接受离散参数而不是数组。

    类似于:

    _refreshWorkspace: function(htmlBlocks){
    
      var promises = [];
    
      if('editor' in htmlBlocks){
        promises.push(
          app.destroy(this.editor).then((function(){
            this.editor.empty().append(htmlBlocks.editor);
          }).bind(this)).then((function(){
            app.refresh(this.editor);
          }).bind(this))
        );
      }
    
      if('listPanels' in htmlBlocks){
        promises.push(
          app.destroy(this.list).then((function(){
            this.list.empty().append(htmlBlocks.listPanels);
          }).bind(this)).then((function(){
            app.refresh(this.list);
          }).bind(this))
        );
      }
    
      if('listNav' in htmlBlocks){
        // similar code block       
      }
    
      return $.when.apply($, promises);
    },
    

    下面是一个使用随机 Deferred 秒:

    function doSomething() {
      var promises = [];
      var d1, d2, d3;
      
      d1 = new $.Deferred();
      promises.push(d1.promise());
      setTimeout(function() {
        snippet.log("Resolving d1");
        d1.resolve(1);
      }, Math.floor(Math.random() * 1000));
      
      d2 = new $.Deferred();
      promises.push(d2.promise());
      setTimeout(function() {
        snippet.log("Resolving d2");
        d2.resolve(2);
      }, Math.floor(Math.random() * 1000));
      
      d3 = new $.Deferred();
      promises.push(d3.promise());
      setTimeout(function() {
        snippet.log("Resolving d3");
        d3.resolve(3);
      }, Math.floor(Math.random() * 1000));
      
      return $.when.apply($, promises);
    }
    
    // Use it
    doSomething().then(function() {
      snippet.log("All resolved");
    });
    <!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
    <script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
        2
  •  1
  •   Roamer-1888    11 年前

    如前所述,这个问题的简单答案是将个人承诺与 $.when.apply(null, promiseArray) .

    然而,如果问题中的所有代码都代表了要应用于所有html块的处理方式,那么您可以更进一步。

    jQuery.map() 将对对象的ownProperties进行操作,因此可以利用它进行迭代 htmlBlocks ,生成了一个简洁、概括的主例程,其中包含一些支持哈希。

    _refreshWorkspace: function(htmlBlocks) {
        var that = this; // avoids the need for .bind(this) in the promise chain and the methodsHash
        var propHash = {
            'editor': 'editor',
            'listPanels': 'list'
        };
        // All the "other unrelated code" is defined here
        var methodsHash = {
            'editor': null,
            'listPanels': function(key, obj) {
                ...
            },
            ...
        };
        //And the main routine is a concise $.map(htmlBlocks, ...) structure. 
        var promises = $.map(htmlBlocks, function(html, key) {
            var obj = that[propHash[key]];
            return app.destroy(obj).then(function() {
                obj.empty().append(html); //if empty() and append() are jQuery methods then this line is synchronous.
                return app.refresh(obj);// if app.destroy() is asynch and theanable, then it seems safe to assume that app.refresh() is also asynch and theanable. Therefore return the result here.
            }).then(function() {
                if(methodsHash[key]) {
                    methodsHash[key](key, obj);
                }
            });
        });
    
        //Now aggregate `promises` into a single promise which resolves when all the promises resolve, or rejects when any of the promises rejects.
        return $.when.apply(null, promises);
    },
    

    现在,为了迎合所有其他html块,只需在 propHash 和null或函数 methodsHash 。如果主例程是全面的,则不需要修改。

    IMHO,这是组织代码的更好方法。