You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

注册页JSON解析语法错误求助:Uncaught Syntax Error意外token 'S'

解决注册页面JSON解析语法错误问题

错误根源

控制台提示的Uncaught Syntax Error: Unexpected token 'S',是因为前端收到的不是合法JSON格式响应,而是PHP后端抛出的SQL错误信息(以SQLSTATE[H"开头)。当数据库操作出错时,后端直接输出了错误文本,而非标准JSON结构,导致前端JSON.parse()解析失败。


分步修复代码

1. 前端JavaScript:增加异常捕获与请求规范

修改handle_result函数,添加解析异常捕获,避免脚本崩溃;同时完善send_data函数的请求头设置与错误处理:

function _(element){
    return document.getElementById(element);
}

var signup_button = _("signup_button");
signup_button.addEventListener("click",collect_data);

function collect_data(){
    signup_button.disabled = true;
    signup_button.value = "Loading...Please wait..";

    var myform = _("myform");
    var inputs = myform.getElementsByTagName("INPUT");

    var data = {};
    for (var i = inputs.length - 1; i >= 0; i--) {
        var key = inputs[i].name;
        switch(key){
            case "username":
                data.username = inputs[i].value;
                break;
            case "email":
                data.email = inputs[i].value;
                break;
            case "gender_male":
            case "gender_female":
                if(inputs[i].checked){
                    data.gender = inputs[i].value;
                }
                break;
            case "password":
                data.password = inputs[i].value;
                break;
            case "password2":
                data.password2 = inputs[i].value;
                break;
        }
    }
    send_data(data,"signup");
}

function send_data(data,type){
    var xml = new XMLHttpRequest();

    xml.onload = function(){
        if(xml.readyState == 4 && xml.status == 200){
            handle_result(xml.responseText);
            signup_button.disabled = false;
            signup_button.value = "Signup";
        } else {
            console.log("HTTP错误状态码:", xml.status);
            var error = _("error");
            error.innerHTML = "请求失败,请检查网络";
            error.style.display = "block";
            signup_button.disabled = false;
            signup_button.value = "Signup";
        }
    }

    // 捕获网络请求错误
    xml.onerror = function() {
        var error = _("error");
        error.innerHTML = "网络连接异常,请稍后重试";
        error.style.display = "block";
        signup_button.disabled = false;
        signup_button.value = "Signup";
    }

    data.data_type = type;
    var data_string = JSON.stringify(data);

    xml.open("POST","api.php",true);
    // 设置请求头,告知服务器发送的是JSON格式数据
    xml.setRequestHeader("Content-Type", "application/json");
    xml.send(data_string);
}

function handle_result(result){
    try {
        var data = JSON.parse(result);
        if(data.data_type == "info"){
            window.location = "index.php";
        }else{
            var error = _("error");
            error.innerHTML = data.message;
            error.style.display = "block";
        }
    } catch(e) {
        // 调试阶段打印原始响应,上线后可删除
        console.log("服务器返回非JSON响应:", result);
        var error = _("error");
        error.innerHTML = "服务器内部错误,请稍后重试";
        error.style.display = "block";
    }
}

2. 后端PHP:统一JSON响应格式与异常捕获

修改api.php,确保所有场景下都返回合法JSON,同时捕获数据库及其他异常:

<?php 
session_start();
// 强制设置响应头为JSON,确保前端正确识别
header("Content-Type: application/json");

$DATA_RAW = file_get_contents("php://input");
$DATA_OBJ = json_decode($DATA_RAW);

$info = (object)[];
$info->data_type = "error";
$info->message = "未知错误";
$output_sent = false;

try {
    // 检查登录状态
    if(!isset($_SESSION['userid']))
    {
        if(isset($DATA_OBJ->data_type) && $DATA_OBJ->data_type != "login" && $DATA_OBJ->data_type != "signup")
        {
            $info->logged_in = false;
            $info->message = "请先登录";
            echo json_encode($info);
            $output_sent = true;
            die;    
        }
    }

    require_once("classes/autoload.php");
    $DB = new Database();

    // 处理业务逻辑
    if(isset($DATA_OBJ->data_type) && $DATA_OBJ->data_type == "signup")
    {
        include("includes/signup.php");
    }elseif(isset($DATA_OBJ->data_type) && $DATA_OBJ->data_type == "login")
    {
        include("includes/login.php");
    }elseif(isset($DATA_OBJ->data_type) && $DATA_OBJ->data_type == "logout")
    {
        include("includes/logout.php");
    }elseif(isset($DATA_OBJ->data_type) && $DATA_OBJ->data_type == "user_info")
    {
        include("includes/user_info.php");
    }elseif(isset($DATA_OBJ->data_type) && $DATA_OBJ->data_type == "contacts")
    {
        include("includes/contacts.php");
    }elseif(isset($DATA_OBJ->data_type) && ($DATA_OBJ->data_type == "chats" || $DATA_OBJ->data_type == "chats_refresh"))
    {
        include("includes/chats.php");
    }elseif(isset($DATA_OBJ->data_type) && $DATA_OBJ->data_type == "settings")
    {
        include("includes/settings.php");
    }elseif(isset($DATA_OBJ->data_type) && $DATA_OBJ->data_type == "save_settings")
    {
        include("includes/save_settings.php");
    }elseif(isset($DATA_OBJ->data_type) && $DATA_OBJ->data_type == "send_message")
    {
        include("includes/send_message.php");
    }elseif(isset($DATA_OBJ->data_type) && $DATA_OBJ->data_type == "delete_message")
    {
        include("includes/delete_message.php");
    }elseif(isset($DATA_OBJ->data_type) && $DATA_OBJ->data_type == "delete_thread")
    {
        include("includes/delete_thread.php");
    }

} catch(PDOException $e) {
    // 捕获数据库异常
    $info->message = "数据库错误:" . $e->getMessage();
    echo json_encode($info);
    $output_sent = true;
} catch(Exception $e) {
    // 捕获其他全局异常
    $info->message = "服务器错误:" . $e->getMessage();
    echo json_encode($info);
    $output_sent = true;
}

// 确保没有提前输出时,返回默认响应
if(!$output_sent) {
    echo json_encode($info);
}

// 以下函数保持不变
function message_left($data,$row)
{
    $image = ($row->gender == "Male") ? "ui/images/user_male.jpg" : "ui/images/user_female.jpg";
    if(file_exists($row->image)){
        $image = $row->image;
    }
    
    $a = "
    <div id='message_left'>
    <div></div>
        <img  id='prof_img' src='$image'>
        <b>$row->username</b><br>
        $data->message<br><br>";

        if($data->files != "" && file_exists($data->files)){
            $a .= "<img src='$data->files' style='width:100%;cursor:pointer;' onclick='image_show(event)' /> <br>";
        }
        $a .= "<span style='font-size:11px;color:white;'>".date("jS M Y H:i:s a",strtotime($data->date))."<span>
    <img id='trash' src='ui/icons/trash.png' onclick='delete_message(event)' msgid='$data->id' />
    </div> ";

    return $a;
}

function message_right($data,$row)
{
    $image = ($row->gender == "Male") ? "ui/images/user_male.jpg" : "ui/images/user_female.jpg";
    if(file_exists($row->image)){
        $image = $row->image;
    }
    
    $a = "
    <div id='message_right'>

    <div>";
    
    if($data->seen){
        $a .="<img src='ui/images/tick.png' style=''/>";
    }elseif($data->received){
        $a .="<img src='ui/images/tick_grey.png' style=''/>";
    }

    $a .= "</div>

        <img id='prof_img' src='$image' style='float:right'>
        <b>$row->username</b><br>
        $data->message<br><br>";

        if($data->files != "" && file_exists($data->files)){
            $a .= "<img src='$data->files' style='width:100%;cursor:pointer;' onclick='image_show(event)' /> <br>";
        }
        $a .= "<span style='font-size:11px;color:#888;'>".date("jS M Y H:i:s a",strtotime($data->date))."<span>

        <img id='trash' src='ui/icons/trash.png' onclick='delete_message(event)' msgid='$data->id' />
    </div>";

    return $a;
}

function message_controls()
{
    return "
    </div>
    <span onclick='delete_thread(event)' style='color:purple;cursor:pointer;'>Delete this thread </span>
    <div style='display:flex;width:100%;height:40px;'>
        <label for='message_file'><img src='ui/icons/clip.png' style='opacity:0.8;width:30px;margin:5px;cursor:pointer;' ></label>
        <input type='file' id='message_file' name='file' style='display:none' onchange='send_image(this.files)' />
        <input id='message_text' onkeyup='enter_pressed(event)' style='flex:6;border:solid thin #ccc;border-bottom:none;font-size:14px;padding:4px;' type='text' placeHolder='type your message'/>
        <input style='flex:1;cursor:pointer;' type='button' value='send' onclick='send_message(event)'/>
    </div>
    </div>";
}

3. 注册逻辑文件includes/signup.php:规范响应输出

确保signup.php中所有操作都通过$info对象返回JSON,禁止直接输出错误:

<?php
global $info, $DB, $DATA_OBJ, $output_sent;

$info->data_type = "error";
$info->message = "";

// 表单验证
if(empty($DATA_OBJ->username)) {
    $info->message = "用户名不能为空";
    echo json_encode($info);
    $output_sent = true;
    return;
}
if(empty($DATA_OBJ->email)) {
    $info->message = "邮箱不能为空";
    echo json_encode($info);
    $output_sent = true;
    return;
}
if(empty($DATA_OBJ->gender)) {
    $info->message = "请选择性别";
    echo json_encode($info);
    $output_sent = true;
    return;
}
if(empty($DATA_OBJ->password) || $DATA_OBJ->password !== $DATA_OBJ->password2) {
    $info->message = "密码不能为空或两次输入不一致";
    echo json_encode($info);
    $output_sent = true;
    return;
}

// 数据库注册操作
try {
    $query = "INSERT INTO users (username, email, gender, password) VALUES (:username, :email, :gender, :password)";
    $stmt = $DB->connect()->prepare($query);
    $hashed_pwd = password_hash($DATA_OBJ->password, PASSWORD_DEFAULT);
    $stmt->bindParam(':username', $DATA_OBJ->username);
    $stmt->bindParam(':email', $DATA_OBJ->email);
    $stmt->bindParam(':gender', $DATA_OBJ->gender);
    $stmt->bindParam(':password', $hashed_pwd);
    
    if($stmt->execute()) {
        $info->data_type = "info";
        $info->message = "注册成功,即将跳转";
        echo json_encode($info);
        $output_sent = true;
    } else {
        $info->message = "注册失败,请重试";
        echo json_encode($info);
        $output_sent = true;
    }
} catch(PDOException $e) {
    // 处理重复注册等数据库错误
    if(str_contains($e->getMessage(), "Duplicate entry")) {
        if(str_contains($e->getMessage(), "username")) {
            $info->message = "该用户名已被注册";
        } elseif(str_contains($e->getMessage(), "email")) {
            $info->message = "该邮箱已被注册";
        }
    } else {
        $info->message = "数据库操作失败:" . $e->getMessage();
    }
    echo json_encode($info);
    $output_sent = true;
}

关键修改说明

  1. 前端:增加JSON.parse()的异常捕获,避免脚本崩溃;设置请求头Content-Type: application/json,确保后端正确解析请求体。
  2. 后端:强制响应头为JSON,用全局try-catch捕获所有异常,确保无论成功/失败都返回合法JSON结构;禁止直接输出错误文本。
  3. 注册逻辑:统一通过$info对象返回结果,处理重复注册等常见业务错误,给用户明确提示。

内容的提问来源于stack exchange,提问作者valentine makomere

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 08:05:25