使用下面的jquery ajax缓存代码时,jquery ajax中的回调不起作用 [英] callback in jquery ajax not working when using jquery ajax cache code below

查看:96
本文介绍了使用下面的jquery ajax缓存代码时,jquery ajax中的回调不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是我的代码,如果任何ajax调用成功回调,则缓存代码无法正常工作.

Below is my code and issue is with cache code is not working properly if any ajax call has callback in success.

var localCache = {
    /**
     * timeout for cache in millis
     * @type {number}
     */
    timeout: 30000,
    /** 
     * @type {{_: number, data: {}}}
     **/
    data: {},
    remove: function (url) {
        delete localCache.data[url];
    },
    exist: function (url) {
        return !!localCache.data[url] && ((new Date().getTime() - localCache.data[url]._) < localCache.timeout);
    },
    get: function (url) {
        console.log('Getting in cache for url' + url);
        return localCache.data[url].data;
    },
    set: function (url, cachedData, callback) {
        localCache.remove(url);
        localCache.data[url] = {
            _: new Date().getTime(),
            data: cachedData
        };
        if ($.isFunction(callback)) callback(cachedData);
    }
};

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
    if (options.cache) {
        var complete = originalOptions.complete || $.noop,
            url = originalOptions.url;
        //remove jQuery cache as we have our own localCache
        options.cache = false;
        options.beforeSend = function () {
            if (localCache.exist(url)) {
                complete(localCache.get(url));
                return false;
            }
            return true;
        };
        options.complete = function (data, textStatus) {
            localCache.set(url, data, complete);
        };
    }
});

function handleAjaxRequests(url, parameters, headers, method, successHandler, options, errorHandler) {

        if (typeof (method) === 'undefined') {
            method = "GET";
        }
        if (typeof (headers) === 'undefined') {
            headers = "";
        }
        if (typeof (parameters) === 'undefined') {
            parameters = "";
        }
        successHandler = typeof (successHandler) === 'undefined' ? function (data) {} : successHandler;
        errorHandler = typeof (errorHandler) === 'undefined' ? function (data) {} : errorHandler;
        return $.ajax({
            method: method.toUpperCase(),
            url: url,
//            async: false,
            data: parameters,
            headers: headers,
            success: function (data) {
                console.log('hi');
                successHandler(data, options);
                console.log('bye');
            },
            error: function (data) {
                $('.loader').hide();
                errorHandler(data);
            },
        });
    }

根据上面的代码,在成功运行ajax successHandler(data, options);函数之后,应该触发该触发器,但这不是由于上面的缓存处理程序代码引起的.我不知道为什么这不起作用.如果我写一些简单的东西而不是回调函数,那它就起作用了.数据表Ajax回调也存在同样的问题. 在项目中,我必须在全局级别使用上述缓存处理程序,无论ajax请求是来自数据表还是来自任何其他来源.

As per the above code after successfully run ajax successHandler(data, options);function should be the trigger but it not due to above cache handler code. I have no idea why this is not working. If I write simple something rather than callback function it is working. Same issue with datatable Ajax callbacks. I have to use above cache handler at global level in my project doesn't matter ajax request is from datatable or from any other source.

上述缓存代码位于此处 https://stackoverflow.com/a/17104536/2733203

Above cache code is from here https://stackoverflow.com/a/17104536/2733203

推荐答案

正如聊天室中所讨论的,我对您的代码进行了一些更改:

As discussed in the chatroom I've made some changes in your code :

var localCache = {
  /**
   * timeout for cache in millis
   * @type {number}
   */
  timeout: 30000,
  /** 
   * @type {{_: number, data: {}}}
   **/
  data: {},
  remove: function(url) {
    delete localCache.data[url];
  },
  exist: function(url) {
    return !!localCache.data[url] && ((new Date().getTime() - localCache.data[url]._) < localCache.timeout);
  },
  get: function(url) {
    console.log('Getting in cache for url ' + url);
    return localCache.data[url].data;
  },
  set: function(url, cachedData, callback) {
    localCache.remove(url);
    localCache.data[url] = {
      _: new Date().getTime(),
      data: cachedData
    };
    console.debug('caching data for '+url, cachedData);
    if ($.isFunction(callback)) callback(cachedData);
  }
};

$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
  if (options.cache) {
    var complete = originalOptions.complete || $.noop,
      url = originalOptions.url;
    //remove jQuery cache as we have our own localCache
    options.cache = false;
    options.beforeSend = function() {
      if (localCache.exist(url)) {
        console.log('using cache, NO QUERY');
        complete(localCache.get(url));
        return false;
      }
      console.log('sending query');
      return true;
    };
    options.complete = function(data, textStatus) {
      localCache.set(url, data, complete);
    };
  }
});

function handleAjaxRequests(url, parameters, headers, method, successHandler, options, errorHandler) {
  method = method || "GET";
  headers = headers || {};
  parameters = parameters || {};

  return $.ajax({
    method: method.toUpperCase(),
    url: url,
    cache: true,
    //            async: false,
    data: parameters,
    headers: headers,
    success: successHandler,
    error: errorHandler,
  });
}

handleAjaxRequests('/echo/json/', {p1: 'hey'}, null, 'POST', function(data){console.log('first success without cache', data);});

setTimeout(function(){
handleAjaxRequests('/echo/json/', {p1: 'hey'}, null, 'POST', function(data){console.log('success! with cache hopefully', data);});
}, 2000);

在此处拨弄

  1. localCache方法中添加了一些日志,以查看正在发生的情况.缓存从未使用过,因此我添加了缺少的cache:true选项
  2. beforeSend方法内添加了一些日志,以监视缓存和查询之间的切换.一切正常.
  3. 清除参数空检查并删除空的function(){}(使用 $ .noop()顺便说一句
  4. 现在是您问题的核心.回调errorHandlersuccessHandler是参数. $.ajax是异步的!这意味着在执行的某个时刻,在进行此调用之后,您将不确定该变量是否具有相同的值.最简单的解决方案是直接引用该函数,然后让jQuery进行范围管理.最困难的解决方案是将这些功能赋予 ajax设置中的context选项我不推荐.
  1. added some logs in the localCache methods to see what's happening. Cache is never used so I've added the missing cache:true option
  2. Added some logs inside beforeSend method to monitor the toggle between cache and query. Everything works fine.
  3. Cleaned up the arguments null checks and removed empty function(){} (use $.noop() instead btw.
  4. Now the core of your issue. The callbacks errorHandler and successHandler are arguments. $.ajax is asynchronous! it means at some point of the execution, right after this call is made, you won't be sure if the variable has the same value. Easiest solution is to just reference the function directly and let jQuery do the scope management. Hardest solution would be to give these functions to the context option in ajax settings which I don't recommend.

现在,您使用的解决方案使您无需包装方法即可直接调用$.ajax.您为什么不直接使用它?更简单,更不容易出错

Now, the solution you use allows you to directly call $.ajax without a wrapper method. Why don't you use it directly? simpler and less prone to errors

编辑:我真的不喜欢上下文,因此还有另一种选择.

EDIT: I'm really not fond of context so there is another alternative.

function handleAjaxRequests(url, parameters, headers, method, successHandler, options, errorHandler) {
  method = method || "GET";
  headers = headers || {};
  parameters = parameters || {};

  return $.ajax({
    method: method.toUpperCase(),
    url: url,
    cache: true,
    //            async: false,
    data: parameters,
    headers: headers,
    success: (function(handler, opt) {
      return function( /*Anything*/ data, /*String*/ textStatus, /*jqXHR*/ jqXHR) {
        console.log('hi');
        handler(data, opt);
        console.log('bye');
      };
    })(successHandler, options),
    error: (function(handler, opt) {
      return function( /*jqXHR*/ jqXHR, /*String*/ textStatus, /*String*/ errorThrown) {
        console.log('ouch');
        handler(errorThrown);
      };
    })(errorHandler, options),
  });
}

您可以使用此众所周知的javascript技巧( currying )来对函数进行范围划分.

You scope the function with this well known javascript trick aka currying.

此处是新提琴.

编辑2 :如果即使要从缓存中获取,也要运行successHandler,则应使用complete而不是success

EDIT 2: if you want successHandler to run even when getting from cache you should use complete instead of success

function handleAjaxRequests(url, parameters, headers, method, successHandler, options, errorHandler) {
  method = method || "GET";
  headers = headers || {};
  parameters = parameters || {};

  return $.ajax({
    method: method.toUpperCase(),
    url: url,
    cache: true,
    //            async: false,
    data: parameters,
    headers: headers,
    complete: (function(handler, opt) {
      return function( /*Anything*/ data, /*String*/ textStatus, /*jqXHR*/ jqXHR) {
        console.log('hi');
        handler(data, opt);
        console.log('bye');
      };
    })(successHandler, options),
    error: (function(handler, opt) {
      return function( /*jqXHR*/ jqXHR, /*String*/ textStatus, /*String*/ errorThrown) {
        console.log('ouch');
        handler(errorThrown);
      };
    })(errorHandler, options),
  });
}

在这里拨弄.

这篇关于使用下面的jquery ajax缓存代码时,jquery ajax中的回调不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆