Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/451.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript iOS 6上的Safari是否缓存$.ajax结果?_Javascript_Jquery_Ajax_Caching_Mobile Safari - Fatal编程技术网

Javascript iOS 6上的Safari是否缓存$.ajax结果?

Javascript iOS 6上的Safari是否缓存$.ajax结果?,javascript,jquery,ajax,caching,mobile-safari,Javascript,Jquery,Ajax,Caching,Mobile Safari,自从升级到iOS 6后,我们看到Safari的web视图可以随意缓存$.ajax调用。这是在PhoneGap应用程序的上下文中,因此它使用Safari WebView。我们的$.ajax调用是POST方法,我们将cache设置为false{cache:false},但这仍然在发生。我们尝试手动向标题添加时间戳,但没有帮助 我们做了更多的研究,发现Safari只返回具有静态函数签名的web服务的缓存结果,并且不会随调用而改变。例如,想象一个名为以下内容的函数: getNewRecordID(int

自从升级到iOS 6后,我们看到Safari的web视图可以随意缓存$.ajax调用。这是在PhoneGap应用程序的上下文中,因此它使用Safari WebView。我们的$.ajax调用是POST方法,我们将cache设置为false{cache:false},但这仍然在发生。我们尝试手动向标题添加时间戳,但没有帮助

我们做了更多的研究,发现Safari只返回具有静态函数签名的web服务的缓存结果,并且不会随调用而改变。例如,想象一个名为以下内容的函数:

getNewRecordID(intRecordType)
此函数一次又一次地接收相同的输入参数,但每次返回的数据应该不同

一定是苹果急于让iOS 6快速运行,他们对缓存设置太满意了。还有人在iOS 6上见过这种行为吗?如果是,究竟是什么原因造成的

我们发现的解决方法是将函数签名修改为如下内容:

getNewRecordID(intRecordType, strTimestamp)
$.ajaxSetup({ cache: false });
$.ajax({
    type: 'POST',
    headers : { "cache-control": "no-cache" },
    url : ,
    data:,
    dataType : 'json',
    success : function(responseText) {…}

然后始终传入一个TimeStamp参数,并在服务器端丢弃该值。这解决了这个问题。

我刚刚在一个应用程序中遇到了这个问题。我通过以下方式使用JavaScript函数getTime解决了这个问题:

var currentTime = new Date();
var n = currentTime.getTime();
postUrl = "http://www.example.com/test.php?nocache="+n;
$.post(postUrl, callbackFunction);

我花了几个小时才弄明白。如果苹果能将这个缓存问题通知开发者,那就太好了。

经过一番调查,发现iOS6上的Safari将缓存没有缓存控制头甚至没有缓存控制的帖子:max age=0

我发现防止这种缓存在全局级别发生的唯一方法是设置缓存控制:无缓存,而不必在服务结束调用时对随机查询字符串进行攻击

因此:

无缓存控制或Expires headers=iOS6 Safari将缓存 缓存控制最大年龄=0,立即过期时间=iOS6 Safari将缓存 缓存控制:无缓存=iOS6 Safari将不缓存 我怀疑苹果是在利用第9.5节关于POST的HTTP规范中的这一点:

对此方法的响应不可缓存,除非响应 包括适当的缓存控制或Expires标头字段。然而 303 See Other响应可用于指示用户代理 检索可缓存的资源

所以理论上你可以缓存帖子回复…谁知道呢。但迄今为止,没有其他浏览器制造商认为这是一个好主意。但是,当没有设置缓存控制或Expires头时,这并不能解释缓存,只有当设置了一些缓存控制或Expires头时。所以它一定是一只虫子

下面是我在Apache配置的正确部分中使用的内容,以我的整个API为目标,因为实际上我不想缓存任何东西,甚至不想缓存数据。我不知道的是如何为帖子设置这个

Header set Cache-Control "no-cache"
更新:只是注意到我没有指出只有当帖子是相同的,所以更改任何帖子数据或URL,你就没事了。因此,您可以像其他地方提到的那样,向URL添加一些随机数据或一点POST数据

更新:如果您希望在Apache中这样做,您可以将no缓存限制为POST:

SetEnvIf Request_Method "POST" IS_POST
Header set Cache-Control "no-cache" env=IS_POST

我在从ASP.NET webservice获取数据时遇到了同样的问题

这对我很有用:

public WebService()
{
    HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    ...
}

假设您使用jQuery,则为所有web服务请求提供简单的解决方案:

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
    // you can use originalOptions.type || options.type to restrict specific type of requests
    options.data = jQuery.param($.extend(originalOptions.data||{}, { 
      timeStamp: new Date().getTime()
    }));
});
阅读有关jQuery预过滤器调用的更多信息


如果您没有使用jQuery,请检查所选库的文档。它们可能具有类似的功能。

根据应用程序的不同,您现在可以使用Safari>Advanced>Web Inspector在iOS 6中解决问题,这对解决这种情况很有帮助

将手机连接到Mac上的Safari,然后使用开发者菜单对web应用进行故障排除

更新到iOS6后,清除iPhone上的网站数据,包括特定于使用Web视图的应用程序的数据。只有一个应用程序有问题,这在IOS6测试期间解决了问题,从那时起就没有真正的问题

您可能还需要查看您的应用程序,如果在自定义应用程序的WebView中,请查看NSURLCache

我想这取决于你的问题的真实性质,实施情况等等


Ref:$.ajax调用

最后,我找到了一个解决上传问题的方法

在JavaScript中:

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


虽然添加cache buster参数以使请求看起来不同似乎是一个可靠的解决方案,但我建议不要这样做,因为这会损害任何依赖实际缓存的应用程序。使API输出正确的头是最好的解决方案,即使这比向调用者添加缓存清除器稍微困难。

我在pagemethods、webservice等方面的解决方法

protected void Application_BeginRequest(object sender, EventArgs e)
{
    Response.Cache.SetCacheability(HttpCacheability.NoCache);
}

只有在中添加pragma:no cache头之后,它才能使用。缓存控制:没有缓存是不够的。

您也可以通过执行以下操作修改函数来解决此问题 从1.7.1开始,从第7212行开始到Ajax函数的顶部。此更改将为所有POST请求激活jQuery的内置反缓存功能

完整的脚本可在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 : "");
    }
}
致:


为了解决添加到主屏幕的WebApps的此问题,需要遵循两种最受欢迎的解决方法。需要关闭Web服务器上的缓存,以防止新请求被缓存,并且需要向每个post请求添加一些随机输入,以便已缓存的请求能够通过。请参阅我的帖子:


警告:适用于通过在请求中添加时间戳而不关闭服务器缓存来实现变通方法的任何人。如果你的应用程序被添加到主屏幕,每个post响应现在都将被缓存,清除safari缓存不会清除它,而且它似乎不会过期。除非有人有办法清除,否则这看起来像是潜在的内存泄漏

我发现了一个解决办法,让我好奇它为什么会起作用。在阅读Tadej关于ASP.NETWeb服务的回答之前,我试图想出一些可行的方法

我并不是说这是一个好的解决方案,但我只是想在这里记录它

主页:包括一个JavaScript函数checkStatus。该方法调用另一个方法,该方法使用jqueryajax调用来更新html内容。我使用setInterval调用checkStatus。当然,我遇到了缓存问题

解决方案:使用另一个页面调用更新

在主页面上,我设置了一个布尔变量runUpdate,并在body标记中添加了以下内容:

<iframe src="helper.html" style="display: none; visibility: hidden;"></iframe>
在helper.html的中:

<meta http-equiv="refresh" content="5">
<script type="text/javascript">
    if (parent.runUpdate) { parent.checkStatus(); }
</script>

因此,如果从主页调用checkStatus,我将获得缓存的内容。如果我从子页面调用checkStatus,我会得到更新的内容。

这就是GWT-RPC的解决方法

class AuthenticatingRequestBuilder extends RpcRequestBuilder 
{
       @Override
       protected RequestBuilder doCreate(String serviceEntryPoint) 
       {
               RequestBuilder requestBuilder = super.doCreate(serviceEntryPoint);           
               requestBuilder.setHeader("Cache-Control", "no-cache");

               return requestBuilder;
       }
}

AuthenticatingRequestBuilder builder = new AuthenticatingRequestBuilder();
((ServiceDefTarget)myService).setRpcRequestBuilder(builder);    

我希望这能对其他开发者在这个问题上把头撞到墙上有所帮助。我发现以下任何一种情况都会阻止iOS 6上的Safari缓存POST响应:

在请求头中添加[缓存控制:无缓存] 添加可变URL参数,如当前时间 在响应头中添加[pragma:no cache] 在响应头中添加[缓存控制:无缓存] 我的解决方案是:在Javascript中,所有AJAX请求都是POST

$.ajaxSetup({
    type: 'POST',
    headers: { "cache-control": "no-cache" }
});
我还将[pragma:no cache]头添加到我的许多服务器响应中


如果使用上述解决方案,请注意,设置为global:false的任何$.ajax调用都不会使用$.ajaxSetup中指定的设置,因此需要再次添加标头。

GWT-RPC服务的一个快速解决方法是将其添加到所有远程方法中:

getThreadLocalResponse().setHeader("Cache-Control", "no-cache");

这是Baz1nga答案的更新。由于options.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();
  }
});
从我自己的博客帖子:

如何修复:有多种方法可以防止缓存请求。建议的方法是添加无缓存标头。就是这样做的

jQuery: 检查iOS 6.0并按如下方式设置Ajax标头:

getNewRecordID(intRecordType, strTimestamp)
$.ajaxSetup({ cache: false });
$.ajax({
    type: 'POST',
    headers : { "cache-control": "no-cache" },
    url : ,
    data:,
    dataType : 'json',
    success : function(responseText) {…}
泽普托伊斯: 检查iOS 6.0并按如下方式设置Ajax头:

getNewRecordID(intRecordType, strTimestamp)
$.ajaxSetup({ cache: false });
$.ajax({
    type: 'POST',
    headers : { "cache-control": "no-cache" },
    url : ,
    data:,
    dataType : 'json',
    success : function(responseText) {…}
服务器端 爪哇: 在将任何数据发送到客户机之前,请确保将其添加到页面顶部

网 或

PHP 对于那些使用Struts1的人,我是如何解决这个问题的

web.xml


我能够通过组合使用$.ajaxSetup和在我的帖子的url而不是帖子参数/正文中附加时间戳来修复我的问题。这是基于先前答案的建议

$(document).ready(function(){
    $.ajaxSetup({ type:'POST', headers: {"cache-control","no-cache"}});

    $('#myForm').submit(function() {
        var data = $('#myForm').serialize();
        var now = new Date();
        var n = now.getTime();
        $.ajax({
            type: 'POST',
            url: 'myendpoint.cfc?method=login&time='+n,
            data: data,
            success: function(results){
                if(results.success) {
                    window.location = 'app.cfm';
                } else {
                    console.log(results);
                    alert('login failed');
                }
            }
        });
    });
});

此JavaScript代码段与jQuery和jQuery Mobile配合使用效果非常好:

$.ajaxSetup({
    cache: false,
    headers: {
        'Cache-Control': 'no-cache'
    }
});
只需在jQuery加载后将其放在JavaScript代码中的某个位置,最好是在执行AJAX请求之前,它应该会有所帮助。

在iPad 4/iOS 6上不适用的事情:

我的请求包含:缓存控制:无缓存

//asp.net's:
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache)
向jQuery ajax调用添加缓存:false

 $.ajax(
        {
            url: postUrl,
            type: "POST",
            cache: false,
            ...
只有这一点起到了作用:

var currentTime = new Date();
var n = currentTime.getTime();
postUrl = "http://www.example.com/test.php?nocache="+n;
$.post(postUrl, callbackFunction);

我认为您已经解决了您的问题,但让我分享一下关于web缓存的想法

的确,您可以在服务器端、客户端的每种语言中添加许多头文件,还可以使用许多其他技巧来避免web缓存,但始终认为您永远无法知道客户端连接到服务器的位置,您永远无法知道他是否在使用酒店“热点”使用Squid或其他缓存产品的连接

如果用户使用代理隐藏其真实位置,等等。避免缓存的唯一方法是请求中的时间戳(如果未使用)

例如:

/ajax_helper.php?ts=3211321456

然后,您必须通过的每个缓存管理器都没有在缓存存储库中找到相同的URL并重新下载页面内容。

而我的登录和注册页面就像火中的符咒 fox,IE和Chrome。。。我在SafariforiOS和OSX中一直在努力解决这个问题,几个月前我在SO上找到了一个解决方法

<body onunload="">
或者通过javascript

<script type="text/javascript">
window.onunload = function(e){
    e.preventDefault();
    return;
};
</script>   
这是一件很难看的事情,但在一段时间内有效


我不知道为什么,但如果将onunload事件返回null,则页面不会在Safari中缓存。

我建议一种变通方法,将函数签名修改为如下内容:

getNewRecordID(intRecordType, strTimestamp)
$.ajaxSetup({ cache: false });
$.ajax({
    type: 'POST',
    headers : { "cache-control": "no-cache" },
    url : ,
    data:,
    dataType : 'json',
    success : function(responseText) {…}
GetNewRecordidRecordType,strTimestamp
然后始终传入一个TimeStamp参数,并在服务器端丢弃该值。这就解决了这个问题。

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

解决办法令人难以置信。请等1秒,然后再打电话。在我们的测试中,只需要一次重复,但我们编写的代码最多可以调用4次。我们不确定是否需要1s等待,但我们不想冒着重复呼叫的风险给服务器增加负担

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

两个有问题的AJAX调用都使用了:POST、Asynchronously=true、setRequestHeader='Content-Type'、'application/x-www-form-urlencoded'

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

iOS13没有做到这一点,Chrome和Firefox也没有。我们没有任何运行iOS 11或iOS 12的测试设备。也许其他人可以测试一下


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

这绝对令人震惊。我们也花了几个小时试图找出什么东西停止工作了。Safari正在缓存我们的AJAX登录,它可以发布帖子,并且有阻止缓存的标题,所以它只返回上次使用的JSON,甚至没有尝试服务器……难以置信!我们将不得不破解一个补丁,但你永远不应该缓存帖子,这太疯狂了。将你的解决方案作为答案而不是问题的更新发布。帖子请求是非幂等的,这意味着它们不应该被缓存,除非响应特别建议通过其响应头进行缓存。要让苹果解决这个问题,请在上提交一个bug。IETF HTTPbis工作组主席马克·诺丁汉(Mark Nottingham)今天就写了一篇有趣的博文:我知道苹果的做法,但我们看到了对post请求的缓存响应,即使我们的响应没有包含任何缓存控制或Expires头。就是这个实例,iOS6不应该缓存并发送每个请求。这种情况没有发生。您引用的HTTP规范部分没有证明iOS 6的缓存行为是正确的。默认行为应为不缓存POST响应,即未定义缓存控制标头时。该行为违反规范,应视为错误。任何构建xml/json api web服务的人都应该使用缓存控制来修饰他们的POST响应:没有缓存来解决这个问题。POST请求是非幂等的,这意味着除非响应特别建议通过其响应头进行缓存,否则不应该对其进行缓存。正如David所说,这显然违反了您引用的句子。如果没有缓存控制或Expires标头字段,则显然不包括适当的此类标头。然而,您自己的调查显示,在这种情况下,它会被缓存。请编辑您的答案。有人知道结果在设备上缓存了多长时间吗?我尝试过杀掉safari并重新启动手机,但它仍然被缓存。我知道它可以清除浏览器缓存,但我想知道,对于曾经有过这个问题的用户来说,它需要多长时间才能消失。不是每个人都会想到清除他们的缓存…我打算评论一下使用{cache:false}作为$.post或$.ajaxSetup的选项,但是根据,这些参数被忽略;jQuery将“从不缓存”post请求,但不考虑浏览器。也许一个更简洁的选择是使用$.ajaxPrefilter为请求添加时间戳。我花了将近5个小时来解决这个问题,最后添加时间戳将完成技巧函数send_ajaxmy_data,refresh。。请参阅此处,它对我不起作用,服务器响应:无效的原始JSON:timeStamp asp.net/iis 7.5$.ajax{cache:false…}怎么样?当它附加一个=[时间戳]时,它会工作吗?我没有这么好的房子

测试itI的设备发布了Karussell提出的解决方案的完整实现。请看下面我的答案。@Karussell。刚刚尝试设置$.ajax{cache:false…}。这并不能解决iOS6上POST请求的问题。大概是因为JQuery根据他们的文档假设没有浏览器愚蠢到可以缓存post请求。使用POST获取的页面永远不会被缓存,因此jQuery.ajaxSetup中的cache和ifModified选项对这些请求没有影响。这不起作用。它不会合并post参数。Dave的帖子是一个更好的解决方案。虽然在大多数情况下我都同意你的观点,但我认为解决这个问题的真正办法是让苹果正确地实现HTTP。考虑到这一点,在此之前,我不会责怪很多开发人员实现了最简单的解决方案。对我来说,修改jquery实现是一个最简单的修复方法,因为它允许我进行一次编辑,并确信它对我的整个站点都是活动的。所有响应都会缓存到手机上的文件或内存中吗?我不是这样。我在我的url上附加了一个时间戳,而不是post参数,无论是从safari浏览还是保存到主屏幕,它都可以正常工作。虽然这并不能直接解决最初的问题,但对于一般设备问题的疑难解答来说,这是非常有用的信息,所以我投了赞成票,这不是一个改变jQuery或者任何你不拥有的代码的好方法。每次你想要更新版本时,你都必须再次进行更改。如果你需要最快的解决方案来减轻苹果的愚蠢,那么这是一个非常有效的方法。此解决方案已用于解决一个每天收到数百万点击率的大型站点的问题,它使我们只需对一个文件进行更改即可完成此任务。您可以查看jQuery.ajaxPrefiler,它允许您在发出请求之前修改ajax请求。您可以使用更优化和更新的安全代码对其进行归档。预过滤器方法的问题是您需要注册过滤器。如果您有一个在加载每个页面时运行的公共脚本,那么很好,但如果没有,则必须为使用ajax的每个页面设置预过滤器。我所面临的情况是,我们有一个JQ文件的公共位置,该文件被用作7个以上单独网站的资源。由于这个错误,我们每小时损失了数千英镑,我建议的方法使我们能够通过更改一个文件在尽可能短的时间内解决这个问题。原则上我同意你的观点,但有时你必须务实!然后可以再次将其添加到该文件的末尾。很好,你解决了这个问题,你的公司一定为你感到高兴。我们大多数人在GWT部署中都有数百种远程方法。是否有一种通用的方法为所有请求设置缓存控制头?非常感谢!我疯狂地想弄明白为什么iPhone与其他平台的表现如此不同。此特定于ASP.NET的解决方案为我节省了大量时间。在iOS6上不起作用请在线程末尾查看我的答案!!!!设置一个仅在IOS 6上应用的条件,内容缓存对任何应用程序都是至关重要的。这是错误的正确解决方案。问题在于iOS 6将为来自缓存的POST请求提供服务,而不是将它们发送到服务器。错误并不在于它缓存了POST请求的响应,这是允许的。如果您仍然希望从缓存中检索POST请求的响应,以便后续获取对该URI的请求,请使用此解决方案。这对我来说是可行的,但我不知道如何实现。我已经在ajaxSetup中指定了cache:false,并查看了请求头,这归结为cache-Control:no-cache和Pragma:no-cache,但它仍然会在iPad上缓存。然后,当我在ajaxSetup中添加头:{cache control:no cache}时,它将缓存控制头加倍为no cache,no cache,并停止缓存。这里发生了什么?工作得很好-您还可以将参数$.ajax{type:'POST',headers:{'cache control':'no cache'},等等。}什么是[pragma:no cache]?pragma键的用途是什么?我也认为这是最好的方法,而不是使用附加参数的解决方法。我们只在需要的调用上添加了此项,对于总是具有相同返回的调用,缓存可能对最终用户是一件好事。添加时间戳不是一个好主意,请尝试Dave的解决方案。对于.NET,一个好的无缓存属性投了什么反对票?这是重要的信息缓存:false不适用于iPad4/iOS6,asp.net的:HttpContext.Current.Response.cache.SetCacheabilityHttpCacheability.NoCacheFor Postery:自2017年起,$.ajax cache:false将url附加查询参数=Date.prototype.getTime,因此,应该不再需要手动添加时间戳了。旧答案,但我的两分钱:这通常是一个很好的建议,大多数有能力的人都能理解 web开发人员,但在jQuery的特定情况下,如果您创建了$.ajax并将选项设置为{cache:false},那么jQuery本身将自动在幕后添加一个缓存,而无需执行任何其他操作。