0

$.ajaxを使用してcss/js / jst(javascriptテンプレート)をロードするこのコードがあり、リクエストの後にリクエストを実行し、一度に1つだけ実行し、非同期で実行するようにしたいと思います。

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 に答える