Is Safari on iOS 6 caching $.ajax results?

前端 未结 25 908
轮回少年
轮回少年 2020-11-22 09:34

Since the upgrade to iOS 6, we are seeing Safari\'s web view take the liberty of caching $.ajax calls. This is in the context of a PhoneGap application so it is

相关标签:
25条回答
  • 2020-11-22 10:05

    In order to resolve this issue for WebApps added to the home screen, both of the top voted workarounds need to be followed. Caching needs to be turned off on the webserver to prevent new requests from being cached going forward and some random input needs to be added to every post request in order for requests that have already been cached to go through. Please refer to my post:

    iOS6 - Is there a way to clear cached ajax POST requests for webapp added to home screen?

    WARNING: to anyone who implemented a workaround by adding a timestamp to their requests without turning off caching on the server. If your app is added to the home screen, EVERY post response will now be cached, clearing safari cache doesn't clear it and it doesn't seem to expire. Unless someone has a way to clear it, this looks like a potential memory leak!

    0 讨论(0)
  • 2020-11-22 10:05

    We found that older iPhones and iPads, running iOS versions 9 & 10, occasionally return bogus blank AJAX results, perhaps due to Apple's turning down CPU speed. When returning the blank result, iOS does not call the server, as if returning a result from cache. Frequency varies widely, from roughly 10% to 30% of AJAX calls return blank.

    The solution is hard to believe. Just wait 1s and call again. In our testing, only one repeat was all that was ever needed, but we wrote the code to call up to 4 times. We're not sure if the 1s wait is required, but we didn't want to risk burdening our server with bursts of repeated calls.

    We found the problem happened with two different AJAX calls, calling on different API files with different data. But I'm concerned it could happen on any AJAX call. We just don't know because we don't inspect every AJAX result and we don't test every call multiple times on old devices.

    Both problem AJAX calls were using: POST, Asynchronously = true, setRequestHeader = ('Content-Type', 'application/x-www-form-urlencoded')

    When the problem happens, there's usually only one AJAX call going on. So it's not due to overlapping AJAX calls. Sometimes the problem happens when the device is busy, but sometimes not, and without DevTools we don't really know what's happening at the time.

    iOS 13 doesn't do this, nor Chrome or Firefox. We don't have any test devices running iOS 11 or 12. Perhaps someone else could test those?

    I'm noting this here because this question is the top Google result when searching for this problem.

    0 讨论(0)
  • 2020-11-22 10:07

    It worked with ASP.NET only after adding the pragma:no-cache header in IIS. Cache-Control: no-cache was not enough.

    0 讨论(0)
  • 2020-11-22 10:11

    I suggest a workaround to modify the function signature to be something like this:

    getNewRecordID(intRecordType, strTimestamp) and then always pass in a TimeStamp parameter as well, and just discard that value on the server side. This works around the issue.

    0 讨论(0)
  • 2020-11-22 10:13

    For those that use Struts 1, here is how I fixed the issue.

    web.xml

    <filter>
        <filter-name>SetCacheControl</filter-name>
        <filter-class>com.example.struts.filters.CacheControlFilter</filter-class>
    </filter>
    
    <filter-mapping>
        <filter-name>SetCacheControl</filter-name>
        <url-pattern>*.do</url-pattern>
        <http-method>POST</http-method>
    </filter-mapping>
    

    com.example.struts.filters.CacheControlFilter.js

    package com.example.struts.filters;
    
    import java.io.IOException;
    import java.util.Date;
    import javax.servlet.*;
    import javax.servlet.http.HttpServletResponse;
    
    public class CacheControlFilter implements Filter {
    
            public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
    
            HttpServletResponse resp = (HttpServletResponse) response;
            resp.setHeader("Expires", "Mon, 18 Jun 1973 18:00:00 GMT");
            resp.setHeader("Last-Modified", new Date().toString());
            resp.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0");
            resp.setHeader("Pragma", "no-cache");
    
            chain.doFilter(request, response);
        }
    
        public void init(FilterConfig filterConfig) throws ServletException {
        }
    
        public void destroy() {
        }
    
    }
    
    0 讨论(0)
  • 2020-11-22 10:14

    I think you have already resolved your issue, but let me share an idea about web caching.

    It is true you can add many headers in each language you use, server side, client side, and you can use many other tricks to avoid web caching, but always think that you can never know from where the client are connecting to your server, you never know if he are using a Hotel “Hot-Spot” connection that uses Squid or other caching products.

    If the users are using proxy to hide his real position, etc… the real only way to avoid caching is the timestamp in the request also if is unused.

    For example:

    /ajax_helper.php?ts=3211321456
    

    Then every cache manager you have to pass didnt find the same URL in the cache repository and go re-download the page content.

    0 讨论(0)
提交回复
热议问题