为何JS的readyStateChangeHandler同时返回成功与失败结果?
问题描述
在function readyStateChangeHandler(xhttp)函数中,网站能正常显示返回的表格,但该处理函数会同时输出成功与失败两种结果,且“get search result”按钮下方会显示来自该函数的错误信息。
问题原因
onreadystatechange事件会在XMLHttpRequest的readyState状态变化时触发多次,而非仅在请求完成时触发。readyState包含5个状态值:
- 0: 未初始化
- 1: 已打开
- 2: 已发送
- 3: 正在接收响应
- 4: 响应完成
你的代码中,只要readyState不等于4或状态码不是200,就会执行失败逻辑,导致请求过程中的前4次状态变化都会触发handleStatusFailure,提前渲染错误信息。尽管最后readyState变为4且状态码200时会执行成功逻辑显示表格,但错误信息已经残留。
修复方案
修改readyStateChangeHandler函数,仅当readyState等于4(请求完成)时,再根据状态码判断成功或失败;同时在请求成功时清空错误信息容器,避免残留提示。另外修正displayObj函数中HTML字符串的语法错误(多余<td>标签、style属性分号缺失)。
修复后的完整代码:
function makeAjaxQuery() { // 创建XMLHttpRequest实例 var xhttp = new XMLHttpRequest(); // 绑定状态变化处理函数 xhttp.onreadystatechange = function() { readyStateChangeHandler(xhttp); }; // 异步发起GET请求 xhttp.open("GET", "xxxxxxx-A3-Q6.json", true); xhttp.send(); } // readyState状态变化处理函数 function readyStateChangeHandler(xhttp) { // 仅在请求完成(readyState=4)时处理结果 if (xhttp.readyState == 4) { if (xhttp.status == 200) { // 请求成功 handleStatusSuccess(xhttp); console.log('success') } else { // 请求完成但状态异常 console.log('failure') handleStatusFailure(xhttp); } } } // 请求失败处理 function handleStatusFailure(xhttp) { var displayDiv = document.getElementById("display"); displayDiv.innerHTML = "XMLHttpRequest failed: status " + xhttp.status; } // 请求成功处理 function handleStatusSuccess(xhttp) { // 清空错误信息容器 var displayDiv = document.getElementById("display"); displayDiv.innerHTML = ""; var jsonText = xhttp.responseText; // 解析JSON响应 var obj = JSON.parse(jsonText); // 渲染结果到页面 displayObj(obj); } // 渲染数据为表格 function displayObj(obj) { var table = ""; for (i = 0; i < 5; i++) { table += "<tr><td>" + '<a href="' + obj.result.video[i].link + '"><img src="' + obj.result.video[i].image + '" width=200></a>' + "</td><td>" + '<span style="color:#DA3FA4; font-weight:bold; font-size: 30px;">' + obj.result.video[i].title + "</span>" + "<br/>" + '<span style="font-weight:bold;font-size: 25px;">' + obj.result.video[i].channel + "</span>" + "<br/>" + '<span style="font-weight:bold;font-size: 25px;">' + obj.result.video[i].view + " views" + "</span>" + "<br/>" + '<span style="font-weight:bold; background-color: black; color:white; font-size: 25px;">' + obj.result.video[i].length + "</span>" + "</td></tr>"; } document.getElementById("test").innerHTML = '<h1>Search results</h1><br><span style="font-size: 30px;">Search keyword: Mathematics</span><br>'; document.getElementById("demo").innerHTML = table; } // 绑定按钮点击事件 const start = document.getElementById("getSearch"); start.addEventListener("click", function() { makeAjaxQuery() });
内容的提问来源于stack exchange,提问作者keepmovingforward
相关产品推荐
相关产品推荐

