WebDev: jQuery, JSON, IE and Caching
I’m almost ready to update the production version of UVFood.com. I’ve been testing against Firefox during development, but I can’t possibly deploy the update without testing against other browsers. Safari turned up no surprises, and Opera has turned up a weird little problem that doesn’t make any sense.
But of course it was Internet Explorer that had the biggest issues.
Bookmarking is done via Ajax. When you bookmark a listing the icon changes from a heart with a plus sign to a heart with a minus sign, the count of the number of times the the listing was bookmarked is updated and a message is displayed that confirms the item was bookmarked. This works fine with Safari, Firefox and Opera. Internet Explorer, however, exhibits some truly erratic behavior. When you bookmark a listing in IE everything you expect happens. But when you click again to remove it from the bookmarks - everything that happened the last time happened again.
Entering a review worked, though. But clicking stars to rate a listing had a similar problem.
The problem was that jQuery on IE was caching the JSON results, something it wasn’t doing on Safari or Firefox.
The first thing I tried was to make sure that my server returned a header in the response to tell the client not to cache the results. It’s a simple header line:
Cache-Control: no-cache
Unfortunately this didn’t change anything. It’s still good practice to make sure that your server emits the correct cache control headers, though.
Then I remembered a discussion of jQuery and GET vs. POST methods. GET is meant to be idempotent, no ill effects if it’s repeated (a request to move to position 8 is idempotent; a request to move to the next position is not). And it may be okay to store the results of a GET. POST is meant to be used for other requests.
Unfortunately, the convenience function that jQuery offers for dealing with jSON Ajax requests is getJSON(), which uses a GET request. It’s easy to write a postJSON() convenience function, however. Just add this to your jQuery initialization code:
$.postJSON = function(url, data, callback) { $.post(url, data, callback, "json");
Changing my code to use postJSON() instead of getJSON() solved the problem.