2012-04-25 3 views
0

У меня есть этот код, который будет загружать css/js/jst (шаблоны javascript) с использованием $ .ajax, и я хотел бы, чтобы он запускал запрос после запроса, запускал только один на время и делать это асинхронно.jQuery отложенные объекты и выполняемые функции в порядке

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(); 
    } 
    }()); 

} 

Прямо сейчас, когда код запускает весь запрос при запуске. Он будет ждать, когда будет вызван отложенный вызов .resolve(), но он не будет ждать, пока цикл iterateWhen() начнет итерацию по отложенным [].

В соответствии с документацией jQuery $ .Deferred() будет принимать функцию как необязательный аргумент и будет запускать эту функцию перед возвратом из конструктора, так что это проблема, но я не знаю решения, которое будет делать что я хочу.

С уважением!

ответ

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!"); 

}); 

С уважением!

Смежные вопросы