输入时AJAX搜索建议异常:请求未触发且JSON解析失败
问题概述
实现用户输入时触发AJAX调用suggerimenti_query.php的搜索建议功能,但出现两个核心问题:
- 浏览器F12 Network面板中看不到对
suggerimenti_query.php的请求 - 返回的JSON无法解析
原JavaScript代码
input.addEventListener("input", (event) => { output.innerHTML = "Cerca " + document.getElementById("tophead-searchbar").value + " su Nevent"; var searchqueryajax = new XMLHttpRequest; ajaxquerylink = "suggerimenti_query.php?query=" + document.getElementById("tophead-searchbar").value; searchqueryajax.addEventListener("load", innerhtmlqueries()); searchqueryajax.open("GET", ajaxquerylink); searchqueryajax.send(); function innerhtmlqueries() { queriesarray = JSON.parse(searchqueryajax.responseText); } });
原PHP代码
$query = $_REQUEST["query"]; $queryresults = mysqli_query($name, "SELECT * FROM search_queries WHERE MATCH(ID, QUERY) AGAINST('$query') LIMIT 7"); if ($queryresults->num_rows > 0) { $autocompleteresults = array(); while($row = mysqli_fetch_array($queryresults)) { $results["ID"] = $row["ID"]; $results["value"] = $row["QUERY"]; $results["type"] = $row["TIPO"]; array_push($autocompleteresults, $results); } } echo json_encode($autocompleteresults);
同文件内正常运行的AJAX代码参考
var checkajaxiflogged = new XMLHttpRequest(); checkajaxiflogged.addEventListener("load", checkajaxiflogged_function); checkajaxiflogged.open("GET", "topbarprofileinformation.php"); checkajaxiflogged.send(); function checkajaxiflogged_function() { topheadjsonresponse = JSON.parse(checkajaxiflogged.responseText); document.getElementById("tophead-account-img").style.backgroundImage = "url('../beta/immagini_profilo/" + topheadjsonresponse.profiloimg + "')"; if (topheadjsonresponse.isloggedin == "yes") { document.getElementById("tophead-accedi-btn").style.display = "none"; document.getElementById("tophead-account-img").style.display = "block"; document.getElementById("Immagine-Profilo-Menu-Principale").style.backgroundImage = "url('../beta/immagini_profilo/" + topheadjsonresponse.profiloimg + "')"; document.getElementById("Nome-Profilo-Menu-Principale").innerHTML = topheadjsonresponse.displayname; document.getElementById("Username-Profilo-Menu-Principale").innerHTML = "@" + topheadjsonresponse.username; } }
错误分析与修复步骤
JavaScript端问题修复
事件监听函数绑定错误
原代码中searchqueryajax.addEventListener("load", innerhtmlqueries());加了括号,导致innerhtmlqueries函数被立即执行,而非在请求完成时触发。应去掉括号,传递函数引用:searchqueryajax.addEventListener("load", innerhtmlqueries);未声明变量引发全局冲突
ajaxquerylink和queriesarray未用var/let/const声明,会成为全局变量引发潜在冲突,需添加声明:let ajaxquerylink = "suggerimenti_query.php?query=" + encodeURIComponent(event.target.value); let queriesarray;URL参数未编码
输入内容含特殊字符(如空格、&等)时会破坏URL结构,需用encodeURIComponent编码查询参数:ajaxquerylink = "suggerimenti_query.php?query=" + encodeURIComponent(inputValue);优化输入值获取逻辑
利用事件对象event.target.value直接获取输入值,避免重复调用document.getElementById:const inputValue = event.target.value; output.innerHTML = `Cerca ${inputValue} su Nevent`;添加防抖减少重复请求(可选)
输入事件触发过于频繁会导致大量重复请求,可添加防抖函数控制请求频率:let debounceTimer; input.addEventListener("input", (event) => { clearTimeout(debounceTimer); debounceTimer = setTimeout(() => { // 原AJAX逻辑放在此处 }, 300); });
修复后的完整JavaScript代码:
input.addEventListener("input", (event) => { const inputValue = event.target.value; output.innerHTML = `Cerca ${inputValue} su Nevent`; let searchqueryajax = new XMLHttpRequest(); let ajaxquerylink = "suggerimenti_query.php?query=" + encodeURIComponent(inputValue); let queriesarray; searchqueryajax.addEventListener("load", innerhtmlqueries); searchqueryajax.open("GET", ajaxquerylink); searchqueryajax.send(); function innerhtmlqueries() { try { queriesarray = JSON.parse(searchqueryajax.responseText); console.log(queriesarray); // 可在此添加搜索建议渲染逻辑 } catch (e) { console.error("JSON解析失败:", e); console.log("响应内容:", searchqueryajax.responseText); } } });
PHP端问题修复
设置JSON响应头
未指定响应类型为JSON,浏览器可能无法正确识别,需在输出前添加:header('Content-Type: application/json; charset=utf-8');初始化结果数组
若查询无结果,$autocompleteresults未定义会导致json_encode报错,需在if外初始化:$autocompleteresults = [];循环内重置结果变量
原代码中$results未在循环内初始化,会导致每次循环覆盖之前的内容,需在while内重置:while($row = mysqli_fetch_array($queryresults)) { $results = []; $results["ID"] = $row["ID"]; $results["value"] = $row["QUERY"]; $results["type"] = $row["TIPO"]; array_push($autocompleteresults, $results); }防范SQL注入
直接拼接用户输入到SQL语句存在注入风险,改用预处理语句:$stmt = $name->prepare("SELECT * FROM search_queries WHERE MATCH(ID, QUERY) AGAINST(?) LIMIT 7"); $stmt->bind_param("s", $query); $stmt->execute(); $queryresults = $stmt->get_result();
修复后的完整PHP代码:
header('Content-Type: application/json; charset=utf-8'); $query = $_REQUEST["query"] ?? ''; $autocompleteresults = []; // 假设$name是已连接的mysqli对象 $stmt = $name->prepare("SELECT * FROM search_queries WHERE MATCH(ID, QUERY) AGAINST(?) LIMIT 7"); $stmt->bind_param("s", $query); $stmt->execute(); $queryresults = $stmt->get_result(); if ($queryresults->num_rows > 0) { while($row = mysqli_fetch_array($queryresults)) { $results = []; $results["ID"] = $row["ID"]; $results["value"] = $row["QUERY"]; $results["type"] = $row["TIPO"]; array_push($autocompleteresults, $results); } } echo json_encode($autocompleteresults);
验证步骤
- 修复代码后,打开浏览器Network面板,切换到XHR分类
- 在搜索框输入内容,查看是否有
suggerimenti_query.php的请求 - 查看请求的响应内容,确认是合法JSON格式
- 检查JavaScript控制台是否有报错信息
内容的提问来源于stack exchange,提问作者lorek006

