JQuery отложенный кеш ajax
Я прочитал верный ответ на этот вопрос относительно использования jQuery Deferred.
Я перебираю массив идентификаторов. Для каждого идентификатора мне нужно получить данные, относящиеся к нему либо из запроса ajax, либо из кеша, если запрос ajax уже успешно возвратил данные раньше.
В течение каждого цикла я использую $.when(), чтобы проверить, возвращает ли getData() что-то из кеша или успешный вызов ajax, прежде чем обрабатывать этот идентификатор. Текущая проблема заключается в том, что обработка идентификатора продолжается в любом случае, не дожидаясь успешного завершения getData() ajax.
Некоторые псевдокоды:
var IDs = ["1", "2", "1", "3", "1"];
//ID "1" is repeated
//data for "1" should should require ajax get the first time
//subsequent processing should get data for "1" from dataCache
var dataCache = [];
function getData(ID){
if (/*data for ID in dataCache*/){
//return data pertaining to ID from dataCache
} else {
return $.getJSON("returnJSONDataByID/" + ID, function(resp){
//push resp data to dataCache
})
}
}
for (/*each item i in IDs*/){
$.when(getData(IDs[i])).then(function(){
//process IDs[i] data
//this is the resolved handler, which should be executed
//when either getData() returns data from the dataCache,
//or $.getJSON succeeds
//PROBLEM: this is currently executing every loop and
//and doesn't wait for the ajax to return resp
})
}
Ответы
Ответ 1
Проблема заключается в том, что ваш цикл немедленно вызовет все вызовы getData
, но результаты будут сохранены только в кеше после вызова JSON. Таким образом, кеш по-прежнему пуст для каждого вызова в цикле, и каждый из них будет выполнять новый запрос JSON.
Решение: вместо результата сохраните объект Deferred
в кеше.
var IDs = ["1", "2", "1", "3", "1"];
var dataCache = {};
function getData(id) {
if (id in dataCache) {
console.log("Cache hit for ID " + id);
return dataCache[id];
} else {
console.log("Retrieving data for ID " + id);
var deferred = $.getJSON("http://jsfiddle.net/echo/jsonp/?callback=?", {
id: id
}, function(response) {
console.log("Retrieved data for ID " + id);
});
dataCache[id] = deferred;
return deferred;
}
}
for (var i=0; i<IDs.length; i++) {
$.when(getData(IDs[i])).then(function(result) {
console.log("result: " + result.id);
});
}
Примечание: это рабочий код, вы можете играть с ним в jsFiddle.