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.