spratap124
spratap124

Reputation: 171

How to memoize jquery ajax response?

I want to cache the jQuery AJAX response so that I don't need to make the network call again.

Below is my JS code:

$(".btn").on("click", function(){
    var id = $(this).data("id");
    var url = "https://alert-carpenter.glitch.me/api/movies/"+id;
    var loadData = memoize(getDataById);

    var data = loadData(url);
    console.log(data);
    // $("#title").html(data.data.title);

});

function getDataById(url,cache){
    $.ajax({
        method:"GET",
        url: url,
        success:function (data){
            console.log("ajax data", data);
            console.log("cache",cache);
            cache[url] = data;     
        }
    });
}

function memoize(fn){
    var cache = {}

    return function(url){
        if(cache[url]!=undefined){
            console.log("loading from cache");
            return cache[url];
        }else{
            console.log("loading from server");
            fn(url,cache)

            return cache[url];
        }
    }
}

AJAX call is getting the response but is it not updating the cache response.

I know if i make Cache variable as global then i can simply update it in jquery ajax success function. but i dont want to make the Cache global.

so here I'm trying to use closure. Please correct me if there is any mistake.

Upvotes: 2

Views: 761

Answers (2)

spratap124
spratap124

Reputation: 171

Thanks for the help @Phil H , I had resolve the undefind error using Promises.

function getDataById(url, cache) {

            return new Promise(function(resolve, reject){
                $.ajax({
                    method: "GET",
                    url: url,
                    success: function (data) {
                        console.log("ajax data", data);
                        console.log("cache", cache);
                        cache[url] = data;
                        resolve(data)
                    },
                    error:function(err){
                        reject(err);
                    }
                });
            });
        }

In the server call

 else {
                    console.log("loading from server");
                    fn(url, cache).then(function(response){
                        console.log("response", response);
                         changeTitle(response);
                    });  

Upvotes: 0

Phil H
Phil H

Reputation: 20131

The problem is that you are memoizing the function every time you respond to the button press. You have

$(".btn").on("click", function(){
    //...
    var loadData = memoize(getDataById);
    ... loadData(input) ...
});


function memoize(fn){
    var cache = {}

    return function(url){
        if(cache[url]!=undefined){
            console.log("loading from cache");
            return cache[url];
        }else{
            console.log("loading from server");
            fn(url,cache)

            return cache[url];
        }
    }
}

So when you call memoize it is constructing a new closure with access to a new cache and returning that. Try creating the memoized loadData outside instead:

var loadData = memoize(getDataById);

$(".btn").on("click", function(){
    //...
    ... loadData(input) ...
});

That way it's the same closure with the same cache that gets called several times.

Upvotes: 2

Related Questions