jQuery deferred ajax cache

2019-03-04 08:36发布

I read the top answer to this question regarding the use of jQuery Deferred.

I'm looping through an array of IDs. For each ID, I need to get data pertaining to it either from an ajax request, or from a cache if an ajax request had already successfully returned the data before.

During each loop, I use a $.when() to observe whether getData() returns something from cache or a successful ajax call, before processing that ID. The current problem is that the ID processing proceeds anyways without waiting for getData()'s ajax to succeed.

Some pseudocode:

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条回答
做个烂人
2楼-- · 2019-03-04 09:04

The problem is that your loop will fire all getData calls immediately, but you results are only stored in the cache once the JSON call returns. Thus, the cache is still empty for every call in the loop and each will perform a new JSON request.

Solution: instead of the result store the Deferred object in the cache.

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

Note: this is working code, you can play with it in jsFiddle.

查看更多
登录 后发表回答