使用$ .ajax()接收HTTP 304代码

时间:2016-04-08 20:46:46

标签: php jquery ajax http

我正在开发一个应用程序,它使用jQuery $ .ajax()函数将HTML内容加载到DIV标记中。 $ .ajax函数每隔几秒运行一次以获得更新。 HTML内容(PHP脚本)相当大,我不想将其加载到div中,除非内容自上次加载后实际发生了更改。我需要知道304何时返回并且什么都不做 - 而不是将HTML从缓存加载到div中。

我尝试过设置:

ifModified: true

并且这似乎没有按预期返回错误。

这给我留下了两个问题:

1)jQuery是否认为该页面每次都是新的,因为它正在加载动态页面 - 即使页面自上次加载后没有改变?

2)如果不回答问题1,那么是否可以进行jQuery $ .ajax()调用并在返回304时执行错误方法?

这是我的测试代码 - 只是为了看看我能否抓住304:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>AJAX Conditional GET Request Test</title>

<script type="text/javascript" src="../jquery/jquery-2.1.4.min.js"></script>

</head>

<body>
<input type="submit" name="button" id="button" value="Check for updates" onclick="javascript:runUpdate();" />
<div id="status" style="width: 100px; height: 12px;"></div>


<script type="text/javascript">

    function runUpdate()
    {

        var today = new Date();
        var h = today.getHours();
        var m = today.getMinutes();
        var s = today.getSeconds();

        var time = h+":"+m+":"+s;

        $.ajax({
            type: "GET",
            url: "../dir/phpscriptthatsometimesupdates.php",
            ifModified: true,
            success: function(data){
                $("#status").html("Updated "+time);
            },
            error: function(data, status, error){
                $("#status").html("Not updated "+time);
            }
        });

    }

    </script>

</body>
</html>

每次我运行测试时都会说文件已经更新 - 即使它没有。

我还尝试使用“If-Modified-Since”使用未来日期但没有成功:

headers: {"If-Modified-Since": "Sun, 10 Apr 2016 00:00:00 GMT"}

服务器正在运行:

Apache 2.2.15 (CentOS)
PHP 5.6.17
jQuery 2.1.4

更新

我尝试调用使用过的PHP文件:

header("Last-Modified: Fri, 08 Apr 2016 00:00:00 GMT");

将Last-Modified设置为过去的时间。我使用浏览器工具进行了检查,发现Last-Modified已发送。从AJAX到此脚本的5次连续调用未显示错误。

我也阅读了How to check if jQuery.ajax() request header Status is "304 Not Modified"?,但它描述的内容似乎与jQuery文档相反,后者解释了ifModified参数:

ifModified (default: false)
Type: Boolean
Allow the request to be successful only if the response has changed 
since the last request. This is done by checking the Last-Modified 
header. Default value is false, ignoring the header. In jQuery 1.4 this 
technique also checks the 'etag' specified by the server to catch 
unmodified data.
或者我错过了什么?根据链接的帖子,我也尝试过:

headers: {"If-Modified-Since": "Fri, 08 Apr 2016 00:00:00 GMT"}

但没有成功。

2 个答案:

答案 0 :(得分:0)

https://httpstatuses.com/304

How to check if jQuery.ajax() request header Status is "304 Not Modified"?

jquery将处理304响应,因为它将是200响应,因此永远不会调用您的错误函数。

答案 1 :(得分:0)

根据我的发现,不可能像How to check if jQuery.ajax() request header Status is "304 Not Modified"?中所述直接捕获304,但仍然可以对xhr.getResponseHeader进行内部比较(&#34; Last-Modified&# 34;)由加载内容之前具有存储值的HEAD请求检索。虽然此解决方案没有专门查看304,但它确实允许脚本根据它的最后修改时间来决定是否加载内容,而不是连续加载缓存内容并浪费资源。

这个想法的基础来自我在这里找到的优秀写作:http://www.raymondcamden.com/2012/04/05/Using-jQuery-to-conditionally-load-requests/

也可以在此处找到:https://gist.github.com/cfjedimaster/2313466

然而,当我在这篇文章中尝试了示例代码时,我遇到了浏览器缓存HEAD响应并始终尝试加载旧内容的问题,即使文件已更新。为了使示例有效,我在$ .ajax()HEAD请求调用中添加了cache:false。

正如@cmorrissey所指出的,我们正在检查更新的PHP脚本必须发送一个Last-Modified标头:

header("Last-Modified: Mon, 11 Apr 2016 00:00:00 GMT");

为了知道PHP脚本的内容是否发生了变化,我们可以使用PHP脚本加载的文件的Last-Modified时间来设置Last-Modified via header()以生成内容。这样,我们将始终知道PHP脚本是否具有新内容。如果我们从磁盘加载文件,则可以使用filemtime()获取此时间;如果我们正在远程加载,则可以从文件中获取Last-Modified标头。

下面是一个完整的,有效的示例,减去我们要检查更新的PHP脚本(somefile.php)以及它将检查更新的JSON或文本文件。

<!DOCTYPE html>
<html>
<head>
<title>AJAX Conditional GET Request Test</title>

<script type="text/javascript" src="jquery-2.1.4.min.js"></script>

</head>

<body>
<input type="submit" name="button" id="button" value="Check for updates" onclick="javascript:runUpdate();" />
<div id="status" style="width: 300px; height: 12px;"></div>


<script type="text/javascript">

    var resourceLastTime = "";

    function runUpdate()
    {

        var today = new Date();
        var h = today.getHours();
        var m = today.getMinutes();
        var s = today.getSeconds();
        var time = h+":"+m+":"+s;

        var resourceUrl = "somefile.php";

        if(resourceLastTime != "")
        {
            $.ajax({
                type:"HEAD",
                url: resourceUrl,
                cache: false,
                success: function(res,code,xhr){

                    if(resourceLastTime != xhr.getResponseHeader("Last-Modified"))
                    {
                        getUrl(resourceUrl);
                        $("#status").html("Updated "+time);
                    }
                    else
                    {
                        $("#status").html("Not updated "+time);
                    }
                },
                error: function(data, status, error){
                    $("#status").html(error+" "+status+" "+time);
                }
            });
        }
        else
        {
            getUrl(resourceUrl);
            $("#status").html("First load "+time);
        }
    }



    function getUrl(urlToGet)
    {
        var urlContents = "";

        $.ajax({
            url:urlToGet,
            type:"get",
            cache:false,
            success:function(res,code,xhr) {
                resourceLastTime = xhr.getResponseHeader("Last-Modified");
                //must process res here due to asynchronous nature of $.ajax() function
            }                    
         });
    }

    </script>

</body>
</html>