dragonmantank
dragonmantank

Reputation: 15456

Stop jQuery .load response from being cached

I have the following code making a GET request on a URL:

$('#searchButton').click(function() {
    $('#inquiry').load('/portal/?f=searchBilling&pid=' + $('#query').val());            
});

But the returned result is not always reflected. For example, I made a change in the response that spit out a stack trace but the stack trace did not appear when I clicked on the search button. I looked at the underlying PHP code that controls the ajax response and it had the correct code and visiting the page directly showed the correct result but the output returned by .load was old.

If I close the browser and reopen it it works once and then starts to return the stale information. Can I control this by jQuery or do I need to have my PHP script output headers to control caching?

Upvotes: 247

Views: 175858

Answers (14)

Adam Gordon Bell
Adam Gordon Bell

Reputation: 3093

You can replace the jquery load function with a version that has cache set to false.

(function($) {
  var _load = jQuery.fn.load;
  $.fn.load = function(url, params, callback) {
  if ( typeof url !== "string" && _load ) {
        return _load.apply( this, arguments );
  }
    var selector, type, response,
      self = this,
      off = url.indexOf(" ");

    if (off > -1) {
      selector = stripAndCollapse(url.slice(off));
      url = url.slice(0, off);
    }

    // If it's a function
    if (jQuery.isFunction(params)) {

      // We assume that it's the callback
      callback = params;
      params = undefined;

      // Otherwise, build a param string
    } else if (params && typeof params === "object") {
      type = "POST";
    }

    // If we have elements to modify, make the request
    if (self.length > 0) {
      jQuery.ajax({
        url: url,

        // If "type" variable is undefined, then "GET" method will be used.
        // Make value of this field explicit since
        // user can override it through ajaxSetup method
        type: type || "GET",
        dataType: "html",
        cache: false,
        data: params
      }).done(function(responseText) {

        // Save response for use in complete callback
        response = arguments;

        self.html(selector ?

          // If a selector was specified, locate the right elements in a dummy div
          // Exclude scripts to avoid IE 'Permission Denied' errors
          jQuery("<div>").append(jQuery.parseHTML(responseText)).find(selector) :

          // Otherwise use the full result
          responseText);

        // If the request succeeds, this function gets "data", "status", "jqXHR"
        // but they are ignored because response was set above.
        // If it fails, this function gets "jqXHR", "status", "error"
      }).always(callback && function(jqXHR, status) {
        self.each(function() {
          callback.apply(this, response || [jqXHR.responseText, status, jqXHR]);
        });
      });
    }

    return this;
  }
})(jQuery);

Place this somewhere global where it will run after jquery loads and you should be all set. Your existing load code will no longer be cached.

Upvotes: 2

NickStees
NickStees

Reputation: 459

If you want to stick with Jquery's .load() method, add something unique to the URL like a JavaScript timestamp. "+new Date().getTime()". Notice I had to add an "&time=" so it does not alter your pid variable.

$('#searchButton').click(function() {
$('#inquiry').load('/portal/?f=searchBilling&pid=' + $('#query').val()+'&time='+new Date().getTime());            
});

Upvotes: 3

user3586251
user3586251

Reputation:

This code may help you

var sr = $("#Search Result");
sr.load("AJAX-Search.aspx?q=" + $("#q")
.val() + "&rnd=" + String((new Date).getTime())
.replace(/\D/gi, ""));

Upvotes: 0

Marshall
Marshall

Reputation: 1160

Here is an example of how to control caching on a per-request basis

$.ajax({
    url: "/YourController",
    cache: false,
    dataType: "html",
    success: function(data) {
        $("#content").html(data);
    }
});

Upvotes: 116

Gomes
Gomes

Reputation: 3330

Another approach to put the below line only when require to get data from server,Append the below line along with your ajax url.

'?_='+Math.round(Math.random()*10000)

Upvotes: 9

user1545320
user1545320

Reputation: 31

Do NOT use timestamp to make an unique URL as for every page you visit is cached in DOM by jquery mobile and you soon run into trouble of running out of memory on mobiles.

$jqm(document).bind('pagebeforeload', function(event, data) {
    var url = data.url;
    var savePageInDOM = true;

    if (url.toLowerCase().indexOf("vacancies") >= 0) {
        savePageInDOM = false;
    }

    $jqm.mobile.cache =  savePageInDOM;
})

This code activates before page is loaded, you can use url.indexOf() to determine if the URL is the one you want to cache or not and set the cache parameter accordingly.

Do not use window.location = ""; to change URL otherwise you will navigate to the address and pagebeforeload will not fire. In order to get around this problem simply use window.location.hash = "";

Upvotes: 3

techexpert
techexpert

Reputation: 2506

I noticed that if some servers (like Apache2) are not configured to specifically allow or deny any "caching", then the server may by default send a "cached" response, even if you set the HTTP headers to "no-cache". So make sure that your server is not "caching" anything before it sents a response:

In the case of Apache2 you have to

1) edit the "disk_cache.conf" file - to disable cache add "CacheDisable /local_files" directive

2) load mod_cache modules (On Ubuntu "sudo a2enmod cache" and "sudo a2enmod disk_cache")

3) restart the Apache2 (Ubuntu "sudo service apache2 restart");

This should do the trick disabling cache on the servers side. Cheers! :)

Upvotes: 0

NGRAUPEN
NGRAUPEN

Reputation: 124

Sasha is good idea, i use a mix.

I create a function

LoadWithoutCache: function (url, source) {
    $.ajax({
        url: url,
        cache: false,
        dataType: "html",
        success: function (data) {
            $("#" + source).html(data);
            return false;
        }
    });
}

And invoke for diferents parts of my page for example on init:

Init: function (actionUrl1, actionUrl2, actionUrl3) {

var ExampleJS= {

Init: function (actionUrl1, actionUrl2, actionUrl3)           ExampleJS.LoadWithoutCache(actionUrl1, "div1");

ExampleJS.LoadWithoutCache(actionUrl2, "div2"); ExampleJS.LoadWithoutCache(actionUrl3, "div3"); } },

Upvotes: 6

John Millikin
John Millikin

Reputation: 200746

You have to use a more complex function like $.ajax() if you want to control caching on a per-request basis. Or, if you just want to turn it off for everything, put this at the top of your script:

$.ajaxSetup ({
    // Disable caching of AJAX responses
    cache: false
});

Upvotes: 427

Sasha
Sasha

Reputation: 61

/**
 * Use this function as jQuery "load" to disable request caching in IE
 * Example: $('selector').loadWithoutCache('url', function(){ //success function callback... });
 **/
$.fn.loadWithoutCache = function (){
 var elem = $(this);
 var func = arguments[1];
 $.ajax({
     url: arguments[0],
     cache: false,
     dataType: "html",
     success: function(data, textStatus, XMLHttpRequest) {
   elem.html(data);
   if(func != undefined){
    func(data, textStatus, XMLHttpRequest);
   }
     }
 });
 return elem;
}

Upvotes: 6

user208444
user208444

Reputation:

Try this:

$("#Search_Result").load("AJAX-Search.aspx?q=" + $("#q").val() + "&rnd=" + String((new Date()).getTime()).replace(/\D/gi, ''));

It works fine when i used it.

Upvotes: 0

nickf
nickf

Reputation: 545995

For PHP, add this line to your script which serves the information you want:

header("cache-control: no-cache");

or, add a unique variable to the query string:

"/portal/?f=searchBilling&x=" + (new Date()).getTime()

Upvotes: 4

Xian
Xian

Reputation: 76591

This is of particular annoyance in IE. Basically you have to send 'no-cache' HTTP headers back with your response from the server.

Upvotes: 4

Lou Franco
Lou Franco

Reputation: 89152

One way is to add a unique number to the end of the url:

$('#inquiry').load('/portal/?f=searchBilling&pid=' + $('#query').val()+'&uid='+uniqueId());

Where you write uniqueId() to return something different each time it's called.

Upvotes: 35

Related Questions