0

我有这段代码将使用 $.ajax 加载 css/js/jst(javascript 模板),我想让它在请求后运行一个请求,一次只运行一个,并异步执行。

var getStuff = function(resources, progressCallback, errorCallback, successCallback, doneCallback){

  var deferreds = [];
  var deferreds_progressCallback = [];
  var len = resources.length;

  for(var idx = 0; idx < len; idx++){

    var resource = resources[idx];

    var dfd = jQuery.Deferred(function(self){
      self.notify(resource);
      (function(resource){
        jQuery.ajax({
          cache: false,
          url: resource,
          dataType: 'text',
          error: function(xhr, status, error){
            self.reject(resource);
          },
          success: function(data, status, xhr){
            if(typeof(data) != 'string'){
              console.log(typeof(data));
            }
            if(resource.match(/.css$/)){
              $('head').append("<style type='text/css'>" + data + "</style>");
            }else if(resource.match(/.jst$/)){
              var templates_div = jQuery("<div style='display:none;'></div>").appendTo('body');
              templates_div.append(data);
            }else if(resource.match(/.js$/)){
              jQuery.globalEval(data);
            }
            self.resolve(resource);
          }
        });
      })(resource);
    });

    deferreds.push(dfd);
    deferreds_progressCallback.push(resource);

  }

  deferreds.reverse();
  deferreds_progressCallback.reverse();

  (function iterateWhen(){
    if(len--){
      jQuery.when(deferreds[len])
      .then(function(resource){
        successCallback(resource);
          iterateWhen();
      })
      .fail(function(resource){
        errorCallback(resource);
      })
      .progress(function(resource){
        progressCallback(resource);
      });
    }else{
      doneCallback && doneCallback();
    }
  }());

}

现在,该代码将在启动时运行所有请求。它将等待 deferred.resolve() 被调用,但不会等待 iterateWhen() 循环开始迭代 deferreds[]。

根据 jQuery 文档,$.Deferred() 将接受一个函数作为可选参数,并在从构造函数返回之前运行该函数,所以这就是问题所在,但我不知道有一个解决方案可以满足我的需求。

问候!

4

1 回答 1

0

我终于这样做了:

function getStuff(resources, progressCallback, errorCallback, successCallback, doneCallback){

  function inject(resource){
    var dfd = jQuery.Deferred();
    dfd.notify(resource);

    jQuery.ajax({
      cache: false,
      url: resource,
      dataType: 'text',
      error: function(xhr, status, error){
        dfd.reject(resource);
      },
      success: function(data, status, xhr){
        if(resource.match(/.css$/)){
          $('head').append("<style type='text/css'>" + data + "</style>");
        }else if(resource.match(/.jst$/)){
          $('body').append("<div style='display:none;'>" + data + "</div>");
        }else if(resource.match(/.js$/)){
          jQuery.globalEval(data);
        }
        dfd.resolve(resource);
      }
    });

    return dfd;
  };

  var len = resources.length;
  resources.reverse();

  (function iterateWhen(){
    if(len--){
      inject(resources[len])
      .then(function(resource){
        successCallback && successCallback(resource);
        iterateWhen();
      })
      .fail(function(resource){
        errorCallback && errorCallback(resource);
      })
      .progress(function(resource){
        progressCallback && progressCallback(resource);
      });
    }else{
      doneCallback && doneCallback();
    }
  }());

}

所以你只需要这样称呼它:

getStuff([

  /*Load .JS, .JST and .CSS files*/
  /*Only same-domain request!*/
  'foo/bar.js',
  'bar/foo.css'

], function(resource){ /*Progress callback*/

  console.log("Loading " + resource);

}, function(resource){ /*Errors callback*/

  console.log("Error while loading " + resource);

}, function(resource){ /*OK callback*/

  console.log("Loaded " + resource);

}, function(){

  console.log("Finished loading .js, .jst and .css files!");

});

问候!

于 2012-04-26T08:17:56.010 回答