注册页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; }
关键修改说明
- 前端:增加
JSON.parse()的异常捕获,避免脚本崩溃;设置请求头Content-Type: application/json,确保后端正确解析请求体。 - 后端:强制响应头为JSON,用全局
try-catch捕获所有异常,确保无论成功/失败都返回合法JSON结构;禁止直接输出错误文本。 - 注册逻辑:统一通过
$info对象返回结果,处理重复注册等常见业务错误,给用户明确提示。
内容的提问来源于stack exchange,提问作者valentine makomere
相关产品推荐
相关产品推荐

