8

I am sending AJAX GET-requests to a PHP application and would like to cache the request returns for later use.

Since I am using GET this should be possible because different requests request different URLs (e.g. getHTML.php?page=2 and getHTML.php?page=5).

What headers do I need to declare in the PHP-application to make the clients browser cache the request URL content in a proper way? Do I need to declare anything in the Javascript which handles the AJAX-request (I am using jQuery's $.ajax function which has a cache parameter)?

How would I handle edits which change the content of e.g. getHTML.php?page=2 so that the client doesn't fall back to the cached version? Adding another parameter to the GET request e.g. getHTML.php?page=2&version=2 is not possible because the link to the requested URL is created automatically without any checking (which is preferably the way I want it to be).

How will the browser react when I try to AJAX-request a cached request URL? Will the AJAX-request return success immediately?

Thanks

Willem

John Topley
  • 113,588
  • 46
  • 195
  • 237
Willem
  • 1,094
  • 1
  • 12
  • 23

2 Answers2

9

Add the following headers on the server:

    header("Cache-Control: private, max-age=$seconds");
    header("Expires: ".gmdate('r', time()+$seconds));

Where $seconds has an obvious meaning.

We set an Expires header here even though it should be ignored if Cache-Control header with max-age parameter is set previously because there are clients that do not follow the standard.

Also, check if your server do not issue some other anti-caching headers like Pragma. If so, add Pragma: cache header too.

sanmai
  • 29,083
  • 12
  • 64
  • 76
3

Once you refresh the page, you'll still be making server calls for content, even though you've requested them before. PHP headers won't help you out with that.

I think what you need is a client-side caching mechanism of content already requested from the server in the current page.

For this use-case you can use a hash table in JavaScript and query that before you make a call to the server. This will enhance user experience since the user won't have to wait for another request of content he's already seen.

Here's an example:

//placeholder for hash table as cache
var cache = [];

var getPage = function(pageNr){
    if(cache[pageNr]){
        //content is already in cache, use it from there
        handleContent(cache[pageNr]);
    }
    else{
        //object with parameteres sent with GET request
        var params = {};
        params.page = pageNr;

        $.ajax({
          url: "getHTML.php",
          data: params,
          cache: false,
          success: function(response){
            //handle your response here
            handleContent(response);

            //store the response in the cache for later use
            cache[pageNr] = response;
          }
        });
    }
};

Now requesting pages will first look in the current cache to see if you have the content. If not, it will make the server call and store the response in the cache.

It is similar to the user-experience when scrolling through news in Google Finance

NOTE that if you refresh the page this cache will be erased.

In case of edits to a page you will have to use Maurice Perry's links to Yahoo Exceptional Performance in order to ensure that your server is always returning your latest version of content.

More on hash tables in JavaScript: http://www.mojavelinux.com/articles/javascript_hashes.html

Razvan Caliman
  • 4,509
  • 3
  • 21
  • 24
  • This will create a pretty big cache[] eventually. This is the reason I was hoping to be able to use PHP Headers to use the build-in browser cache (which probably won't affect performance as much as a huge JS array would. – Willem Mar 16 '09 at 15:24
  • Unless you are planning to use this as a single application the cache object shouldn't get unreasonably large. When it does, remember it is still stored on the client, in the user's browser. In any case, you can choose to flush it when it reaches a certain point. – Razvan Caliman Mar 16 '09 at 17:57
  • I am actually doing a single-page "application". Are you sure it's okay to store objects this big on the client? – Willem Mar 19 '09 at 00:48
  • If this will be implemented as a single application you might want to have some quota on that hash. Flush it after it reaches a certain size or when the user is unlikely to return to a page. – Razvan Caliman Mar 19 '09 at 07:41
  • Depending on the content you store in that hash I'd say it's generally safe to assume that most modern browsers can handle it although I recommend you keep your code tidy and clear that cache from time to time. – Razvan Caliman Mar 19 '09 at 07:42
  • pressing the refresh button will cause most browsers to refetch the ajax resource regardless of cache headers sent. But, not if the user just uses back-forward buttons, or clicks link or other normal navigation techniques. refresh means refresh, other cases the browsers will cache it seamlessly. – goat Dec 19 '11 at 23:21
  • `if(cache[pageNr])` will throw "is not defined" error. Proper way of doing it is `if (typeof cache[pageNr] != "underfined"`. – Devtrix.net May 30 '13 at 09:16
  • @Devtrix.net, What makes you say it will throw an error? If the page index is not available in the cache array it will just return undefined, which is a 'falsy' value in JS so the logic goes through the else branch. – Razvan Caliman May 30 '13 at 12:41