GET请求中随机出现JSON的意外结尾

时间:2020-03-01 12:12:31

标签: javascript php mysql json

我正在开发一个简单的Web项目,其中的一项功能(与错误相关)将显示报价,信用和来源。此功能按预期工作,每12秒使用setInterval来调用一个函数,该函数将连接到XAMPP托管的MYSQL服务器,并返回一个随机行作为JSON对象,可用于在页面上显示。下面是Quote检索脚本和PHP:

quotes.js

(function() {
  ajax = new XMLHttpRequest();
  var method = "GET";
  var url = "data.php";
  var asynchronous = true; // revise asynchronous

  var quoteContainer = document.getElementById("quote");
  var authorContainer = document.getElementById("author");

  function getQuote() {

    ajax.onreadystatechange = function(){
      if (this.readyState == 4 && this.status == 200) {

        var data = JSON.parse(this.responseText);
console.log(data)

        quoteContainer.innerHTML =  "\"" + data.Quote + "\""
        authorContainer.innerHTML = data.Author + " - " + "<a href='"+ data.Source +"' target='_blank'>source</a>";

      }

    }

    ajax.open(method,url,asynchronous);
    ajax.send();
  }

  getQuote();
  setInterval(getQuote,12000); //set to 100 for testing

}());

Data.php

<?php
// write secondry query for seasonal messages
$conn = mysqli_connect("localhost","root","","quotes_db");
$sql = "SELECT * FROM quote_table ORDER BY RAND() LIMIT 1;";


$result = mysqli_query($conn,$sql);
$data= mysqli_fetch_assoc($result);

echo json_encode($data);
?>

问题在于,服务器运行时偶尔会返回“空”数据包(标题为错误),我已经使用Chrome开发者控制台检查了网络数据,并且受影响的数据包为空,需要稍长的时间才能返回。我已经检查了数据库表中的特殊字符,这看起来很正常。由于数据包返回null,因此页面为空

  1. 如何停止出现此错误,以便从表中获得连续的随机行流?
  2. 如果答案不是很明显,我应该采取哪些错误测试步骤来找到解决办法?

如果需要更多信息,我可以更新此帖子。

错误日志

3 个答案:

答案 0 :(得分:2)

您可以执行某种错误处理来实现您的目标。

ajax.onreadystatechange = function(){
      if (this.readyState == 4 && this.status == 200) {
        try
        {
            var data = JSON.parse(this.responseText);
        }
        catch (error)
        {
            if (error instanceof SyntaxError)
            {
                // unable to parse the result to json
                // maybe retry?
                // do some kind of errer handling
            }
        }
      }

使用try-catch语句,您只需捕获错误,而不是停止执行脚本,因此您可以自己处理错误。

最诚挚的问候。

编辑:

setInterval(function () 
{ 
    var found = false; 
    var attemptCount = 0;
    var allowedAttempts = 10; // your exit condition, so you wont get stuck in an infinite loop if the server is broken or something
    while (!found && attemptCount < allowedAttempts) 
    { 
        try 
        { 
            getQuote(); 
        } 
        catch (error) 
        { 
            if (error instanceof SyntaxError) 
            { 
                attemptCount++;
                continue; 
            } 
        } 
        found = true; 
    } 
}, 12e3);

编辑2 :(基于您对另一个答案的评论) 如果要进行服务器端验证,则必须修改PHP代码:

$data = []; // set a default return value
$result = mysqli_query($conn,$sql);
if (mysqli_num_rows($result) === 1) // we found a result
{
    $data= mysqli_fetch_assoc($result);
}
echo json_encode($data);

因此,如果同时结合了客户端验证和服务器端验证,则可以肯定:

我们做了什么?

  • 我们实现了服务器端验证,因此通过JSON.parse()时,返回给客户端的结果永远不会抛出错误。为此,您必须对JSON.parse()的结果执行客户端验证,以确保获得有效的结果(因为它可能是空数组)。

  • 如果服务器上发生任何错误(无论出于何种原因)并且无法解析返回的结果,我们只需将整个过程重试n次即可。

最诚挚的问候。

答案 1 :(得分:2)

通常在返回的数据不确定或格式无效时发生。那是JSON.parse()失败的时候。您可以考虑放入try-catch块。

try {
   var data = JSON.parse(this.responseText);
} catch(e) {
   console.log('Unable to parse the string.')
}

此外,如果服务器发送空响应,请考虑将JSON.parse()语句包装在if条件中。

答案 2 :(得分:1)

问题是由您的编码引起的:Jean de La Bruyère由MySQL传输为Jean de La Bruy�re

PHP json_encode()无法处理法语字符的编码,如print_r()结果的mysqli_fetch_assoc()输出所示:

Array
(
    [QuoteID] => 6
    [Quote] => Those who make the worst use of their time are the first to complain of its brevity.
    [Author] => Jean de La Bruy�re
    [Source] => https://www.goodreads.com/author/show/778012.Jean_de_La_Bruy_re
)

由于json_encode()仅接受UTF-8编码的字符串("All string data must be UTF-8 encoded.",请参见PHP文档),因此只需执行一次以下查询,就可以告诉MySQL以UTF-8编码返回每个结果。打开连接后:

mysqli_query($conn, "SET NAMES 'utf8'");