自从升级到iOS 6以来,我们看到Safari的web视图可以自由缓存$。ajax调用。这是在一个PhoneGap应用程序的上下文中,所以它使用Safari WebView。我们的美元。ajax调用是POST方法,我们有缓存设置为false {cache:false},但这仍然发生。我们尝试手动添加一个时间戳到头部,但它没有帮助。

我们做了更多的研究,发现Safari只返回具有静态函数签名的web服务的缓存结果,并且在每次调用之间不会改变。例如,想象一个函数是这样的:

getNewRecordID(intRecordType)

这个函数一遍又一遍地接收相同的输入参数,但它每次返回的数据应该是不同的。

苹果一定是急于让iOS 6运行得令人印象深刻,他们对缓存设置太满意了。有人在iOS 6上看到过这种行为吗?如果是的话,到底是什么原因造成的呢?


我们发现的解决方法是修改函数签名,像这样:

getNewRecordID(intRecordType, strTimestamp)

然后总是传递一个TimeStamp参数,并在服务器端丢弃这个值。这就解决了这个问题。


当前回答

最后,我对上传问题有了一个解决方案。

在JavaScript中:

var xhr = new XMLHttpRequest();
xhr.open("post", 'uploader.php', true);
xhr.setRequestHeader("pragma", "no-cache");

在PHP中:

header('cache-control: no-cache');

其他回答

我们发现,运行iOS 9和10版本的旧iphone和ipad偶尔会返回虚假的空白AJAX结果,可能是由于苹果降低了CPU速度。当返回空白结果时,iOS不调用服务器,就像从缓存中返回结果一样。频率差异很大,大约10%到30%的AJAX调用返回空白。

解决方案令人难以置信。请稍等片刻,然后再打来。在我们的测试中,只需要重复一次,但我们编写的代码最多可以调用4次。我们不确定是否需要1s等待,但我们不想冒着重复调用导致服务器负担过重的风险。

我们发现这个问题发生在两个不同的AJAX调用中,调用不同的API文件,使用不同的数据。但我担心在任何AJAX调用中都可能发生这种情况。我们只是不知道,因为我们没有检查每个AJAX结果,也没有在旧设备上多次测试每个调用。

这两个问题AJAX调用都使用:POST,异步= true, setRequestHeader = ('Content-Type', 'application/x-www-form-urlencoded')

当问题发生时,通常只有一个AJAX调用在进行。所以这不是由于重叠的AJAX调用。有时问题发生在设备忙的时候,但有时不是,没有DevTools,我们真的不知道当时发生了什么。

iOS 13没有这个功能,Chrome和Firefox也没有。我们没有任何运行iOS 11或12的测试设备。也许其他人可以测试一下?

我在这里注意到这一点是因为在搜索这个问题时,这个问题是谷歌的顶部结果。

您还可以通过修改jQuery Ajax函数来解决这个问题,方法是在Ajax函数的顶部执行以下操作(从1.7.1开始)(函数从第7212行开始)。此更改将激活jQuery内置的反缓存功能,用于所有POST请求。

(完整的脚本可以在http://dl.dropbox.com/u/58016866/jquery-1.7.1.js上找到。)

插入到第7221行以下:

if (options.type === "POST") {
    options.cache = false;
}

然后修改以下内容(从第~7497行开始)。

if (!s.hasContent) {
    // If data is available, append data to URL
    if (s.data) {
        s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
        // #9682: remove data so that it's not used in an eventual retry
        delete s.data;
    }

    // Get ifModifiedKey before adding the anti-cache parameter
    ifModifiedKey = s.url;

    // Add anti-cache in URL if needed
    if (s.cache === false) {
        var ts = jQuery.now(),
        // Try replacing _= if it is there
        ret = s.url.replace(rts, "$1_=" + ts);

        // If nothing was replaced, add timestamp to the end.
        s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
    }
}

To:

// More options handling for requests with no content
if (!s.hasContent) {
    // If data is available, append data to URL
    if (s.data) {
        s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
        // #9682: remove data so that it's not used in an eventual retry
        delete s.data;
    }

    // Get ifModifiedKey before adding the anti-cache parameter
    ifModifiedKey = s.url;
}

// Add anti-cache in URL if needed
if (s.cache === false) {
    var ts = jQuery.now(),
    // Try replacing _= if it is there
    ret = s.url.replace(rts, "$1_=" + ts);

    // If nothing was replaced, add timestamp to the end.
    s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
}

这是Baz1nga对答案的更新。因为选项。data不是一个对象,而是一个字符串,我只是把时间戳连接起来:

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
  if (originalOptions.type == "post" || options.type == "post") {

    if (options.data && options.data.length)
      options.data += "&";
    else
      options.data = "";

    options.data += "timeStamp=" + new Date().getTime();
  }
});

对于那些使用Struts 1的人,下面是我解决这个问题的方法。

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() {
    }

}

这个JavaScript代码片段与jQuery和jQuery Mobile一起工作:

$.ajaxSetup({
    cache: false,
    headers: {
        'Cache-Control': 'no-cache'
    }
});

只需将它放在JavaScript代码中的某个地方(在加载jQuery之后,最好在执行AJAX请求之前),它就会有帮助。