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

JavaScript中XMLHttpRequest请求if/else分支同时执行问题排查

问题现象

在JavaScript中使用if (xhr.readyState == 4 && xhr.status == 200)判断XMLHttpRequest请求状态时出现逻辑异常:开发PHP MVC项目个人资料编辑页前端交互时,if、else分支代码均被执行——个人资料编辑操作实际成功,接口正常返回JSON数据,也能正常跳转至Profile页面,但else分支定义的错误提示“Sorry, this content isn't available right now”仍会触发展示。代码保存为本地文件运行时功能完全正常。

核心实现代码
document.querySelector("#Profile_Save").addEventListener("click", () => {
    if (document.querySelector("#Profile_Edit_Email").value.match(/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/)) {
        document.querySelector("#Profile_Edit_Msg").classList.remove("active_success");
        document.querySelector("#Profile_Edit_Msg").classList.remove("active_denger");
        document.querySelector("#Profile_Save").innerHTML = "Loading...";
        document.querySelector("#Profile_Save").classList.remove("active");
        document.querySelector("#Profile_Save").disabled = true;

        document.querySelector("#Profile_Edit_F_Name").disabled = true;
        document.querySelector("#Profile_Edit_L_Name").disabled = true;
        document.querySelector("#Profile_Edit_Email").disabled = true;

        var f_name = document.querySelector("#Profile_Edit_F_Name").value,
            l_name = document.querySelector("#Profile_Edit_L_Name").value,
            email = document.querySelector("#Profile_Edit_Email").value;

        var xhr = new XMLHttpRequest();
        xhr.open("POST", "Api/ProfileEdit", true);
        xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        xhr.onreadystatechange = function() {
            if (xhr.readyState == 4 && xhr.status == 200) { // 成功分支实际执行
                var json = JSON.parse(xhr.responseText);
                if (json.Status == "Ok") {
                    window.location.href = "Profile"; // 跳转逻辑正常生效
                } else {
                    document.querySelector("#Profile_Edit_Msg").classList.remove("active_success");
                    document.querySelector("#Profile_Edit_Msg").classList.add("active_denger");
                    document.querySelector("#Profile_Edit_Msg").innerHTML = json.Message;
                }
            } else { // 错误分支也被执行
                document.querySelector("#Profile_Edit_Msg").classList.add("active_denger");
                document.querySelector("#Profile_Edit_Msg").innerHTML = "Sorry, this content isn't available right now"; // 错误提示弹出
            }
        }
        xhr.send("F_Name=" + f_name + "&L_Name=" + l_name + "&Email=" + email);
        // 发送请求后立刻重置按钮状态
        document.querySelector("#Profile_Save").innerHTML = "Register";
        document.querySelector("#Profile_Save").classList.add("active");
        document.querySelector("#Profile_Save").disabled = false;
        document.querySelector("#Profile_Edit_F_Name").disabled = false;
        document.querySelector("#Profile_Edit_L_Name").disabled = false;
        document.querySelector("#Profile_Edit_Email").disabled = false;
    } else {
        document.querySelector("#Profile_Edit_Msg").classList.add("active_denger");
        document.querySelector("#Profile_Edit_Msg").innerHTML = "Invalid Email Address!";
    }
});

接口返回内容

{"Status":"Ok","Message":"Profile Edit Successfully!"}

实际运行效果

跳转个人主页前,会先展示错误提示,截图如下:
运行效果截图

故障原因

问题出在onreadystatechange事件的判断逻辑上:

  • XMLHttpRequest的onreadystatechange事件会在readyState状态变化时触发,整个请求生命周期一共会触发5次,对应readyState的5个值:
    • 0:请求未初始化
    • 1:已建立服务器连接
    • 2:请求已被服务器接收
    • 3:正在处理请求
    • 4:请求已完成,响应已就绪
  • 现有逻辑判断为「如果不是readyState=4且status=200,就直接走else弹错误提示」,意味着readyState为0/1/2/3的中间阶段,每次事件触发都会执行错误提示逻辑,这就是错误提示提前弹出的根本原因。
  • 另外代码还存在逻辑瑕疵:xhr.send()发送请求后立刻重置了按钮、恢复了表单编辑状态,没有等请求完成,Loading状态根本不会正常生效。
修复方案

调整事件内判断逻辑,仅在readyState=4(请求完成)时处理后续逻辑:请求完成后先统一重置按钮和表单状态,再根据HTTP状态码判断是走成功解析分支还是网络错误分支,请求中间阶段不做任何错误提示。
修正后的核心代码如下:

xhr.onreadystatechange = function() {
    // 仅在请求完全完成时处理逻辑
    if (xhr.readyState === 4) {
        // 统一重置按钮和表单状态,无论请求成功失败都要恢复可操作状态
        document.querySelector("#Profile_Save").innerHTML = "Register";
        document.querySelector("#Profile_Save").classList.add("active");
        document.querySelector("#Profile_Save").disabled = false;
        document.querySelector("#Profile_Edit_F_Name").disabled = false;
        document.querySelector("#Profile_Edit_L_Name").disabled = false;
        document.querySelector("#Profile_Edit_Email").disabled = false;

        if (xhr.status === 200) {
            const json = JSON.parse(xhr.responseText);
            if (json.Status === "Ok") {
                window.location.href = "Profile";
            } else {
                document.querySelector("#Profile_Edit_Msg").classList.remove("active_success");
                document.querySelector("#Profile_Edit_Msg").classList.add("active_denger");
                document.querySelector("#Profile_Edit_Msg").innerHTML = json.Message;
            }
        } else {
            // 只有请求完成但HTTP状态异常时才提示网络错误
            document.querySelector("#Profile_Edit_Msg").classList.add("active_denger");
            document.querySelector("#Profile_Edit_Msg").innerHTML = "Sorry, this content isn't available right now";
        }
    }
}
xhr.send("F_Name=" + encodeURIComponent(f_name) + "&L_Name=" + encodeURIComponent(l_name) + "&Email=" + encodeURIComponent(email));
// 删除原来xhr.send()后面写的重置按钮、恢复表单的代码,这部分逻辑已经移到请求完成的回调里

额外优化点:发送POST参数时用encodeURIComponent转义特殊字符,避免参数里含特殊符号时接口解析异常;另外代码里写的样式类名active_denger是拼写错误,正确应为active_danger,可自行修正。

内容的提问来源于stack exchange,提问作者Uttam Nath

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 23:30:52