Skip to main content

Bug Tracker

Side navigation

#12550 closed bug (fixed)

Opened September 17, 2012 02:15PM UTC

Closed October 16, 2012 08:08PM UTC

jQuery Ajax cache=false doesn't always work

Reported by: k@ailis.de Owned by: jaubourg
Priority: low Milestone: 1.9
Component: ajax Version: 1.8.1
Keywords: Cc:
Blocked by: Blocking:
Description

When sending an ajax request with the "cache" option set to "false" then sometimes the request is still answered from the browser cache. The reason is that fast machines and fast browsers (like Chrome) are able to send multiple Ajax requests in the same millisecond. jQuery only adds the current timestamp to the URL, looks like this is no longer enough.

This page demonstrates the problem:

http://www.ailis.de/~k/permdata/20120917/jquerycache.html

Keep reloading the page on a fast machine and you will sometimes get a red "DUPLICATE" warning instead of a green "OK" indicating a timestamp which was already used for a previous request. On my machine this happens on every 3rd reload or so.

I recommend adding another value to the timestamp to prevent this problem. Maybe a static counter? That's how we workaround the problem currently.

Attachments (0)
Change History (12)

Changed September 17, 2012 02:34PM UTC by dmethvin comment:1

component: unfiledajax
milestone: None1.9
priority: undecidedlow
status: newopen

You need a slower computer.

I suppose we could seed that static counter with the current time at page load and then just increment it on each request. If we do that I'm taking bets on how long we get a bug report that someone was expecting that value to represent the time the request was submitted.

Changed September 17, 2012 02:49PM UTC by k@ailis.de comment:2

The documentation says jQuery adds a "timestamp". It doesn't say in which format. So maybe you can switch from an integer to a floating point number. You could remember the last used millisecond timestamp and then compare it on the next ajax request with the previous one. If they are the same then add a counter after the decimal point. When millisecond timestamp is newer than the previous one then reset the counter. Then you'll end up with timestamp parameters like this:

_=18236178231
_=18236178232
_=18236178232.001
_=18236178232.002
_=18236178233
_=18236178233.001
_=18236178233.002
_=18236178234

Doing it like this jQuery still sends a valid timestamp (Accuracy is somewhat faked but still as accurate as before) and can generate 1000 unique Ajax-URLs per millisecond. Should be enough even for my super computer (Which is only a standard i7 laptop) ;-)

And when JavaScript supports nanosecond timestamps some day then this counter hack could simply be replaced with a real high-precision timestamp.

Changed September 17, 2012 03:04PM UTC by jaubourg comment:3

owner: → jaubourg
status: openassigned

We surely have a bug here but I'd love to know what real-life application will make a gazillion requests to the same **exact same** URL within the same second... seems pretty innefficient to me (as in, why not group the requests?).

Changed September 17, 2012 03:06PM UTC by jaubourg comment:4

@dmethvin Also, shouldn't we aim at fixing this sooner than later (ie. 1.8.2)? It's a minor behaviour change, I agree, but I can see how this situation will only present itself more often.

Changed September 17, 2012 03:32PM UTC by dmethvin comment:5

It doesn't seem very common since this is the first report we've ever had. I'd really like to get 1.8.2 out without any regressions, and my concern is that someone has taken our "timestamp" description to be a pledge that it always represents the starting time of that ajax request. Turning the value into a floating point number might work though, at least that would be trimmed off if the server treated it like an integer. Do you think I'm anticipating a regression that won't occur?

Changed September 17, 2012 03:40PM UTC by k@ailis.de comment:6

@jaubourg It's not a gazillion requests. Two requests are enough. It may work in 99% of all page requests but the hundredth visitor may trigger the error. I can't give you a good real-life example. In our case the browser has to request some unique server-side entity ID in various places. These places are pretty much independent from each other so they send their own ajax requests to the same URL and this sometimes happens in the same millisecond.

@dmethvin Maybe this is the first report for this problem because computers and browsers were not fast enough in the past to trigger this problem. Oh, BTW: Just noticed I get multiple duplicate timestamps in the demo page on every request when using Firefox. Looks like Firefox is even faster as Chrome. That's surprising to me, but off-topic ;-)

Changed September 17, 2012 03:56PM UTC by kayahr comment:7

What about adding another parameter instead when the timestamp was already used in the previous ajax request? Then the timestamp parameter itself is not changed:

_=18236178231
_=18236178232
_=18236178232&__=1
_=18236178232&__=2
_=18236178233
_=18236178233&__=1
_=18236178233&__=2
_=18236178234

But maybe this makes trouble when there is already a parameter with two underscores as name...

Changed September 17, 2012 11:15PM UTC by jaubourg comment:8

I don't really like the idea of adding too much logic (testing if the previous anticache param was the same then reset the counter or increment it). I'd like the fix to be as compact as possible. If we just add a counter at the end of the timestamp (string concatenation style) then, yes, we have a regression, but it's on undocumented behaviour and is as simple to fix as using substr (and it will work for new and ancient versions alike).

Changed October 05, 2012 10:58PM UTC by longdogz comment:9

I hope I'm not breaking protocol by adding information to this bug. Please let me know if I should have entered a new bug, instead.

Just to reinforce that this isn't only happening for one person in one situation, I have an app that seems to be running into this problem. Unfortunately, the environment in which the app runs is complicated enough that I'm not entirely sure the problem is with jQuery, but here goes.

I have a web app that I am trying to get to run as an iPhone app within PhoneGap 2.1.0 using jQuery 1.7.1 and jQuery Mobile 1.1.1. If I run it in Xcode in the iOS 5.1 Simulator, it runs just fine. However, if I run it in the iOS 6 Simulator, after the first time I have logged in and then logged out, when I hit the login API again (using $.ajax()), my success callback gets called. However, the PHP login API is not hit. Note that I found that I could add a millisecond parameter of my own to the URL and that seems to have worked around the problem. :-)

Here's my $.ajax() call:

$.ajax({

type: "POST",

url: base + "login?x=" + msecs,

dataType: 'json',

cache: false,

data: formData,

success: successFunc,

error: errorFunc

});

Like I said, I'm not at all sure this is a problem in jQuery (as opposed to PhoneGap or the iOS 6 Simulator), but this bug does seem to be very applicable.

Changed October 09, 2012 12:26AM UTC by dmethvin comment:10

Changed October 09, 2012 02:10AM UTC by mikesherov comment:11

dmethvin, clearly an apple bug. There are workarounds though involving sent headers that if apple doesn't fix this bug, we can. Just wish there was more clarity into whether apple acknowledges this as a bug.

Changed October 16, 2012 08:08PM UTC by jaubourg comment:12

resolution: → fixed
status: assignedclosed

Uses an additive approach to generating anti-cache parameters rather than a timestamp. Fixes #12550

Changeset: 8bae5e19af30208a25ea357921f46845f6793951