Well, this was a weird one. Yesterday I was working on a project where I made multiple requests to the Random User API. It worked perfectly in Chrome, and Android, but in Safari, I noticed something odd. Even though I made multiple requests, every result was the same, not unique. Here is a simplified version of what I built.
for(var i=0;i<10;i++) {
$.ajax({
url: 'http://api.randomuser.me/',
dataType: 'json',
success: function(data){
console.log(JSON.stringify(data.results[0].user.name));
}
});
}
My code was somewhat more complex (it had Angular, Promises, even kittens thrown in), but this gives you the basic idea. Running this in Chrome I get what I'd expect, 10 random users in the console:

And ten requests in the Network panel:

So far so good. However, in Safari (well, Mobile Safari at first, but today I tested in Safari), something odd happened. Instead of ten random users, I got the same one again and again. (And before someone asks, no, it isn't the for loop or anything like that.)

Naturally I thought - ok - Safari is caching the response. But here is what threw me for a loop. I went into the Timelines panel, turned on Recording, and this is what I saw:

Looking at this, you can see Safari made one network request, which I suppose makes sense, but here is what ticks me off. Nowhere in this panel is any indication that it simply ignored my Ajax calls and used a cache result.
To be clear, I'm totally fine with Safari ignoring my request to an API that is random and deciding it knew better and should cache. Fine. What upsets me is that the dev tools do zero to let the developer know what's going on here. It should report the other 9 requests and flag them as being from a cache or some such. I guess I'll go file a bug report for this (no, I will, because that's the right thing to do), but damn was this frustrating.
For folks curious, I simply added "?safaricanbiteme="+Math.random() to the URL - just like I used to do for older IE.
Archived Comments
If anyone wants to track this bug, it is bug id 21859864.
It’s not in WebKit Bugzilla? https://bugs.webkit.org/sho...
I’ve also tested in Firefox, Edge and IE11 (demo: http://output.jsbin.com/xor... ); they match Chrome. Safari is the outlier here.
In your example, the API does not specify Cache-Control, so I believe it's non specified behavior (user agent is free to cache as it wishes). Due to the nature of that API endpoint being transient you should outreach to them to add in 'Cache-Control: no-cache', that way they are being explicit about the ability for the result to be cached (which is cannot). Cache busting works, but as a general solution it just completely writes off caching.
A Safari engineer had me add it to bugreport.apple.com.
I agree with you that the API provider should absolutely do that, but as I said in the post, this is nothing to do with the fact that it is caching, but the fact that there is no *developer* feedback that XHR requests 2-10 were skipped due to the cache. Make sense?
If you add the argument cache: false to your ajax call, does it still pull just the one record and make only one call?
To be clear, even if it did, that isn't the issue. I feel like I'm not being clear here. :) I can work around the issue w/ a random value in the URL, and maybe cache:false would work too. But that isn't the problem. The problem is that when Safari decides to not make a network request, it needs to _report_ this to the developer. Does that make sense?
Absolutely makes sense. If I'm remembering correctly, IE8 and IE9 do the same thing. Basically they just cache the request and don't bother making the additional calls. The cache: false argument works similar to adding a random value to the URL.
Nice little hack by jQuery there. I was using Angular in the 'real' code, and I know they have their own caching system, but I wonder if they have a hack like this too. FYI, I tried testing my code in IE11 and it worked perfectly. If I had an IE8 VM around I'd check it there too. (Again, not to see it cache, but to see if the dev tools back then showed it.)
Adding
cache: false
makes Safari behave like the other browsers (test: http://jsbin.com/qidaro/edi... ). I’ll have to remember that “cache: false for Safari” rule.Of course - that's only jQuery. Did anyone check the Angular docs to see if $http has something similar? (Yes, I'm being lazy.)
Yep $http.get(url,{cache:false})
We just got bitten by this bug. The strange thing is that it happens only the very first time the page is opened.
In our case we are using content negotiation and returning either JSON or HTML based on the `Accept` header sent from the client.
Has your bug report been addressed? I was unable to find it in Apple's database.
I don't know. I don't even know where the code is anymore.
Ok, I found it, but not sure how to link to it. Bug ID is 21859864.
Looks to still exist.
As an FYI, I consistently see this: For my 10 calls, calls 2-10 are duplicates. So for 10 calls, I get 2 distinct values.
Thank you Raymond for share this! It has been very helpful.
Years later, Safari still returns 200 even when the file hasn't changed. And, it reads it from disk cache. Why isn't it returning 304 ?
You got me. I should have filed a bug report for it.
Some people have mentioned a filed bug with ID 21859864.
Unfortunately Apple are mean and they don't let you view other people's bug reports: https://stackoverflow.com/a...
However, I believe I have found another filed issue for this over on the WebKit bug tracker. Open since 2014 :-|
https://bugs.webkit.org/sho...
This issue is still present, on macos 14 in safari, and also on ios 14 on safari and chrome apps. Im doing 4 GET requests to a single url with a 200ms delay between each, but safari's network tab shows only a single request.