mochikit cache prevention

6 views
Skip to first unread message

Diez B. Roggisch

unread,
Nov 29, 2006, 11:35:04 AM11/29/06
to MochiKit
Hi,

today I had the marvelous joy of making my app work with IE 6. Time to fall to
ones knees and praise Bill - for sure. Such a great browser!

Just one little peculiarity made me stumble - for a few hours only, nothing
really worth mentioning. Caching. Which prevented my beautiful JSON requests
to be actually issued.

Now my colleagues work with dojo, and after I questionend them how they've
setup their server to prevent caching, they tell me that there is a generated
parameter attached to each request that will prevent caching - a timestamp I
presume.

So - is there any chance such a thing could be made (optionally) part of the
Async-package?

Regards,

Diez

Thomas Hervé

unread,
Nov 29, 2006, 12:13:59 PM11/29/06
to MochiKit

Diez B. Roggisch a écrit :

> So - is there any chance such a thing could be made (optionally) part of the
> Async-package?

If a patch is provided, why not. Until then, you have several options:
* define the cache control in your web server (with pragma no-cache and
cache-control).
* Add an argument to loadJSONdoc(): loadJSONdoc('http://toto',
{'no-cache': new Date().getTime()})

--
Thomas

Jorge Godoy

unread,
Nov 29, 2006, 8:34:04 PM11/29/06
to Diez B. Roggisch, MochiKit

I use Math.random to generate a random number with every request. This is
discarded by the application.

--
Jorge Godoy <jgo...@gmail.com>

Bob Ippolito

unread,
Nov 29, 2006, 11:12:49 PM11/29/06
to Jorge Godoy, Diez B. Roggisch, MochiKit

There's always the chance of getting the same random number twice.. A
timestamp with enough precision is generally better. It's *extremely*
unlikely that a single user is going to get the same exact timestamp
twice... there would have to be something seriously wrong with their
UA for that to happen.

-bob

Jorge Godoy

unread,
Nov 30, 2006, 5:05:59 AM11/30/06
to Bob Ippolito, Diez B. Roggisch, MochiKit
"Bob Ippolito" <b...@redivi.com> writes:

> There's always the chance of getting the same random number twice.. A
> timestamp with enough precision is generally better. It's *extremely*
> unlikely that a single user is going to get the same exact timestamp
> twice... there would have to be something seriously wrong with their
> UA for that to happen.

What's the precision for the timestamp? If it doesn't get to at least
milliseconds then it starts being a problem with daylight saving time,
when the time change occurs.

--
Jorge Godoy <jgo...@gmail.com>

Bob Ippolito

unread,
Nov 30, 2006, 5:22:49 AM11/30/06
to Jorge Godoy, Diez B. Roggisch, MochiKit

Date.prototype.getTIme() is defined as an integer number of
milliseconds since the epoch. Daylight savings time or any other
timezone change is totally irrelevant, regardless of the precision.

Even if it was relevant, the chances of doing a request precisely one
hour after a previous request during the one hour per year in which
that happens is a whole lot less than getting the same random number
twice during any session at any time of the year. Especially
considering the fact that most normal people are sleeping during (at
least) the second 2am...

-bob

Diez B. Roggisch

unread,
Nov 30, 2006, 6:54:53 AM11/30/06
to moch...@googlegroups.com, Thomas Hervé

See the patch attached.

One turns on cache prevention via

MochiKit.Async.PREVENT_CACHING_PARAM = 'preventCaching';

The set value is then used as parameter-name. As by your suggestion, I use the
timestamp.

Works great for me so far. I chose the global variable way because I wanted to
be as unobtrusive as possible - after all, if you want this, I presume you
will want it everywhere, and hunting down all async calls that possibly need
an additional parameter is considerably harder.

Diez

prevent_caching.patch

Jorge Godoy

unread,
Nov 30, 2006, 12:50:36 PM11/30/06
to Bob Ippolito, Diez B. Roggisch, MochiKit
"Bob Ippolito" <b...@redivi.com> writes:

> Even if it was relevant, the chances of doing a request precisely one
> hour after a previous request during the one hour per year in which
> that happens is a whole lot less than getting the same random number
> twice during any session at any time of the year. Especially
> considering the fact that most normal people are sleeping during (at
> least) the second 2am...

Time changes earlier here in .br, for example. Anyway, point taken and it is
better using the timestamp then.

--
Jorge Godoy <jgo...@gmail.com>

Martyn Smith

unread,
Nov 30, 2006, 4:21:02 PM11/30/06
to MochiKit
Just as a side note, I found that by POSTING all my data rather than using GET (which is the loadJSONDoc default) that browsers (namely IE) stopped caching when it shouldn't.

Perhaps loadJSONDoc could post by default rather than GET?, or perhaps have an option/another function for doing this?
--
Martyn

Bob Ippolito

unread,
Nov 30, 2006, 4:27:15 PM11/30/06
to Martyn Smith, MochiKit
That's a really bad idea in general. If you want to post, use
something like this::

var d = doXHR(url, {
method: 'POST',
'mimeType': 'text/plain',
'headers': [['Accept', 'application/json']]
}).addCallback(MochiKit.Async.evalJSONRequest);

-bob

David Shoemaker

unread,
Nov 30, 2006, 4:59:26 PM11/30/06
to Bob Ippolito, Martyn Smith, MochiKit
All,
I've had success preventing caching in IE and FF by setting these response headers server-side:
Cache-Control: no-cache, must-revalidate
Expires: Mon, 25 Jul 2005 05:00:00 GMT
Pragma: no-cache

I know this is a javascript-related list, but I prefer to keep as much of this logic on the server as possible, and this seems to work well.  I'm sure you can pick any time in the past for the Expires header.

Bob,
Is what you suggested here the "official" way to POST an xhr with mochikit?  That question comes up all the time on the list and in the irc channel; it would be nice to be able to point people to a definitive answer (if one exists...).

Thanks,
David Shoemaker
--
--- I'd give my right arm to be ambidextrous. ---

Bob Ippolito

unread,
Nov 30, 2006, 5:20:23 PM11/30/06
to David Shoemaker, Martyn Smith, MochiKit
doXHR is just sugar for the three or four lines you'd have if you were
dispatching an XMLHttpRequest manually. It doesn't really do anything
of significance. It doesn't really have anything to do with POST
specifically other than the fact that it can be used to construct a
POST request with arbitrary headers and content (just as it can be
used to do a GET or anything else).

-bob

Bob Ippolito

unread,
Nov 30, 2006, 6:51:32 PM11/30/06
to Lee Eschen, MochiKit
On 11/30/06, Lee Eschen <ashg...@frontiernet.net> wrote:

> Bob Ippolito wrote:
> > That's a really bad idea in general. If you want to post, use
> > something like this::
> >
> > var d = doXHR(url, {
> > method: 'POST',
> > 'mimeType': 'text/plain',
> > 'headers': [['Accept', 'application/json']]
> > }).addCallback(MochiKit.Async.evalJSONRequest);
> >
> Bob, can you expand on your comment above? Why is POSTing a bad idea as
> opposed to GETing? Why is your code sample a better idea?

POSTing is a fine idea if and only if the server expects it. POSTing
by default is a really bad idea because it's semantically not a POST
operation. It also thwarts caching altogether, when you really only
want to thwart caching for volatile documents. Not all documents are
volatile.

For example, the MochiKit documentation generates an index dynamically
by fetching the XHTML documents and parsing out the function
definitions. These XHTML documents really don't change much at all and
should be cached.

-bob

Hamish Friedlander

unread,
Dec 4, 2006, 1:54:00 AM12/4/06
to MochiKit
Hi,

Date.getTime is in milliseconds since the epoch, but browsers rarely
support the full resolution. On my machine, Firefox/2.0/Win32, the
minimum resolution is about 10 milliseconds. You can test this by:

var y = (new Date).getTime() ;
for ( var x = 0 ; x < 100000 ; x++ ) {
if ( y != (new Date).getTime() ) break ;
}

alert( x + ":" + (new Date).getTime() - y ) ;

Which should give 1:1 but on my machine gives about 500:10.

So multiple calls to getTime can return the same number, although if
you're using it for network stuff, the latency will probably stop this
from being a problem. When I need a unique number I append a global
counter onto getTime, like:

var newunique = (new Date).getTime() + "" + (unique++) ;

You can't just use a global counter, because restarting a browser or
reloading the page will give non-unique values. It's still not
strongly unique across multiple windows, but it's not too bad.

I'm against any attempt to make having a dontCache parameter the
default - cherrypy throws when receiveing a method call with an
unknown parameter name, and I suspect other frameworks will do the
same.

A much better solution is server side - IE seems to ignore plenty of
headers which should make it not cache, but this combination seems to
work:

request.setHeader( 'Expires', "Mon, 26 Jul 1997 05:00:00 GMT" )
request.setHeader( 'Cache-Control', 'no-cache, must-revalidate' )
request.setHeader( 'Pragma', 'no-cache' )

Caching is a general issue, not just related to XMLHttpRequest - IE
will also often ignore most caching headers for images, and other
dynamically inserted elements, so server-side headers or src mangling
is needed for them too.

Hamish Friedlander,
Mind Control Dogs

Reply all
Reply to author
Forward
0 new messages