Как запомнить ответ jQuery ajax?


Я хочу кэшировать ответ jQuery AJAX, чтобы мне не нужно было снова совершать сетевой вызов.

Ниже приведен мой код JS:

$(".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 получает ответ, но не обновляет ответ кэша.

Я знаю, что если я сделаю переменную кэша глобальной, то я могу просто обновить ее в jQuery ajax success function. но я не хочу делать кэш глобальным.

Итак, здесь я пытаюсь использовать закрытие. Пожалуйста, поправьте меня, если есть какая-то ошибка.

2 2

2 ответа:

Проблема в том, что вы запоминаете функцию каждый раз, когда реагируете на нажатие кнопки. У вас есть

$(".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];
        }
    }
}
Поэтому, когда вы вызываете memoize, он строит новое замыкание с доступом к новому cache и возвращает его. Попробуйте вместо этого создать memoized loadData снаружи:
var loadData = memoize(getDataById);

$(".btn").on("click", function(){
    //...
    ... loadData(input) ...
});
Таким образом, это одно и то же закрытие с одним и тем же кэшем, которое вызывается несколько раз.

Спасибо за помощь @Phil H, я решил ошибку undefind, используя обещания.

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

В вызове сервера

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