format internet:

…please wait (49% completed)…

Posts Tagged ‘cache’

IE cache for Ajax requests

Posted by javier ramirez on January 14, 2010

A few days ago I ran into an issue that is now obvious but took me a while to figure out. I was programming a chat client and everything was working fine in Firefox and Chrome, but when I tested it on IE (6 and 8) things were not looking so good.

This chat is following the polling pattern, issuing an Ajax call every three seconds to check for any updates and receiving a JSON array with the pending messages, if any. Using prototype.js the code to call the javascript function every three seconds is this

new PeriodicalExecuter(Aspchat.chatRemotePoll, 3);

On IE the chat was initialized properly, the first call to the remote server was working fine, but the periodical poller was not issuing any further calls. At first I thought the problem was on PeriodicalExecuter, but after a bit of debugging I could see “Aspchat.chatRemotePoll” was being called, but the Ajax call inside was apparently ignored.

To make things more interesting, I could see some other Ajax requests were working fine (for example, the one to send messages or to update the user list).

Comparing the requests that were successfully sent with the ones that were ignored, I could see the difference. In the working requests I was using POST (the default when using prototype) but in the ignored calls I was using GET.

Once I saw this, it was easy to diagnose what the problem was. IE was caching the GET requests, even when using AJAX. To be honest, this time I will not even blame IE, since I understand a GET request is subject to cache. In this case, I would even say I prefer the IE behaviour over that of Firefox and Chrome.

There are basically three things you can do to prevent this kind of behaviour:

  • The easy way out would be to convert my GET request to a POST one. Alas, I didn’t want to do it because in this case I was being RESTful and I was using the same URL for two different actions. When calling “/aspchat/messages” via GET I’m asking for new messages, but when calling via POST I’m sending a new message to the channel.
  • Set HTTP headers to control client cache
  • Make the request unique by adding a timestamp (or similar) to the URL

The solution I like the best is the one with HTTP headers, so I just went to my poller action (which by the way is managed via a Rails metal middleware) and added the Cache-Control: no-cache header. Just to be really sure, I also added the timestamp for extra security.

The prototype for the Ajax call with the timestamp looks like this

new Ajax.Request('/aspchat/messages', {
           parameters: {timestamp:new Date().getTime()}, //we need this to avoid IE caching of the AJAX get
           method: 'get',
           onSuccess: function(transport){
               Aspchat.displayChatMessages(eval(transport.responseText));  //pass the JSON array to displayChatMessages
                         }
       });

As an extra ball, you can see how I’m using the onSuccess callback to interpret the JSON I’m receiving from the server.

Now you cannot say you didn’t know your AJAX requests could be cached. Let’s be careful out there.

Posted in 1771, development, internet, javier ramirez, ruby on rails | Tagged: , , , , , | 15 Comments »