0

我想根据一个值动态更改我的网站。我从我的 MySQL 数据库中检索数据,并希望更改尽可能接近实时。我有一些代码在某种程度上可以满足我的要求,但是值的更新似乎失败了,起初它可以工作,然后在几次调用之后,它似乎只是在两个值之间随机切换。

我有三个 php 页面,一个从数据库(database.php)中检索一个值,两个根据数据库值(response1.php 和 response2.php)生成响应。我不认为这些页面是问题的一部分,因为我已经检查过它们是否返回值并且它们返回我想要的。项目的第二部分(可能会失败)是我的主要 html 页面(如下)。我不确定我是否选择了解决问题的最佳技术,或者是否有更好的方法来解决问题。

<html>
<head>
    <script type="text/javascript">
        var databaseanswer, xmlhttp;

        function databasecheck() {
            xmlhttp = new XMLHttpRequest();
            xmlhttp.open("GET", "database.php", true);
            xmlhttp.onreadystatechange = function() {
                if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                    databaseanswer = xmlhttp.responseText;
                    document.getElementById("database").innerHTML = xmlhttp.responseText;
                }
            };
            xmlhttp.send();
        }

        function response() {
            if (databaseanswer == "No Tag") {
                xmlhttp = new XMLHttpRequest();
                xmlhttp.open("GET", "response1.php", true);
                xmlhttp.onreadystatechange = function() {
                    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                        document.getElementById("response").innerHTML = xmlhttp.responseText;
                    }
                };
                xmlhttp.send();
            }
            else {
                xmlhttp = new XMLHttpRequest();
                xmlhttp.open("GET", "response2.php", true);
                xmlhttp.onreadystatechange = function() {
                    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                        document.getElementById("response").innerHTML = xmlhttp.responseText;
                    }
                };
                xmlhttp.send();
            }
        }

        setInterval(databasecheck, 1800);
        setInterval(response, 2000);

    </script>
</head>
<body>
    <p> this is a test site </p>
    <p> response from server: </p>
    <div id="response">
    </div>
    <p> answer from database: </p>
    <div id="database">
    </div>
</body>
</html>

好的,这是我编辑的代码:

<html>
<head>
<script>

function database(){
  var xmlhttp = new XMLHttpRequest();

  xmlhttp.open("GET","responsedatabase.php",false);
  xmlhttp.onreadystatechange=function()
      {
      if (xmlhttp.readyState==4 && xmlhttp.status==200)
      {
        document.getElementById("database").innerHTML=xmlhttp.responseText;
      }
      }
  xmlhttp.send();
}

setInterval(database,1000);

</script>
</head>
<body>
<p>answer from database: </p><div id="database"></div>
</body>
</html>
4

1 回答 1

0

问题是您正在发送多个异步请求并且请求未序列化。请记住,您无法控制请求的响应时间。此外,随着时间的推移,调用responsedatabasecheck调用之间的时间量不断增加。例如。最初,databasecheck将在 1.8 秒后response执行,将在 2 秒后执行;差异为 200 毫秒。第二次,databasecheck3.6秒后response执行,4秒后执行;差异为 400 毫秒。

除此之外,请求的响应时间不受您的控制。您提出的第一个请求不一定是第一个完成的请求。也就是说,即使您序列化对databasecheckresponse函数的调用,如果您不序列化 XHR 调用,您将得到明显随机的结果。也就是说,假设databasecheck返回x并且您发送了一个请求response1.php;虽然它仍在进行中,但假设第二个请求已databasecheck返回y,另一个请求response2.php已启动。现在,根据请求response1.phpresponse2.php完成的顺序,您可能会看到正确或错误的结果。并且,在发生这种情况时,另一个要求database.php可能已经完成,您将再次看到一些不同的结果。这就是结果出现明显随机性的原因。

您需要做的是序列化调用databasecheckresponse函数。也就是说,response只有在请求database.php完成后才发起调用。现在,您需要确保请求之间也没有竞争条件。这有点麻烦,您可能会丢失实时行为。

更好的方法是将调用的结果与对database.php和 的调用的结果结合response1.php起来response2.php。即,将逻辑移至服务器端。将代码放入返回值response1.phpresponse2.php函数中。假设这些 to 函数被命名为response1and response2。在你的database.php. 根据数据库值调用这些函数中的任何一个。将结果与数据库值一起放入关联数组中,并将响应作为 JSON 格式的字符串返回。这样,您将减少一个请求,并且不会出现同步问题。

更新后

您需要在更新的代码中执行以下操作:

var requestInProgress = false;
function database() {
    if(requestInProgress) {
        return;
    }
    var xmlhttp = new XMLHttpRequest();

    xmlhttp.open("GET","responsedatabase.php",false);
    xmlhttp.onreadystatechange=function() {
        if (xmlhttp.readyState == 4) {
            requestInProgress = false;
            if(xmlhttp.status==200) {
                document.getElementById("database").innerHTML=xmlhttp.responseText;
            }
        }
    }
    requestInProgress = true; 
    xmlhttp.send();
}

您也可以减少持续时间,setInterval以确保在前一个请求的结束和新请求的开始之间没有太多延迟。

于 2013-05-18T10:53:36.647 回答