将jQuery AJAX POST请求转为原生JavaScript fetch异步请求时的问题排查与解决咨询
解决原生JavaScript AJAX POST请求的两个问题:JSON解析错误与请求仅执行一次
我来帮你一步步排查并解决这两个问题,都是原生fetch转换时容易踩的坑:
问题1:SyntaxError: Unexpected end of JSON input
这个错误说明fetch尝试解析响应为JSON时失败了,大概率是PHP端的响应格式或响应头有问题。
排查与解决:
给PHP添加正确的响应头:
原PHP代码只是直接echo JSON字符串,但没有告诉浏览器这是JSON格式的内容,这会导致fetch的json()方法解析失败。在PHP的echo语句前必须添加:header('Content-Type: application/json');这是关键,确保服务器返回的响应被识别为标准JSON类型。
检查PHP是否输出了额外内容:
如果PHP代码有Notice、Warning等错误输出(比如变量未定义),这些文本会附加在JSON前面,直接破坏JSON结构。你可以:- 在PHP开头添加
error_reporting(0);暂时屏蔽错误输出(上线前建议开启错误日志而非直接输出到页面) - 或者先用
fetch查看原始响应内容,替换let resultado = await peticion.json();为:
这样能直接看到PHP返回的具体内容,快速定位是否有额外输出破坏了JSON格式。let rawText = await peticion.text(); console.log('原始响应内容:', rawText); // 之后再尝试解析 let resultado = JSON.parse(rawText);
- 在PHP开头添加
问题2:仅发送一次请求且不更新HTML
你的代码有两个核心逻辑漏洞:
- 定义了
ola处理函数,但从来没有调用它,所以获取到结果后根本没执行更新HTML的逻辑; - 只调用了一次
envSoli(),没有像原jQuery那样循环发起请求(原代码是每次请求成功后,根据chenille的递增判断是否继续处理下一行)。
修改后的完整代码:
// 实现原jQuery的beforeSend逻辑 const updateCheckStatus = () => { const checkStatus = document.getElementById("checkStatus"); if (checkStatus) { checkStatus.innerHTML = "<img src=''/>"; } }; const envSoli = async () => { // 发起请求前更新状态 updateCheckStatus(); try { let peticion = await fetch("data.php", { method: "POST", body: `ajax=1&do=check&lista=${encodeURIComponent(leray[chenille])}`, headers: { "Content-type": "application/x-www-form-urlencoded" } }); // 先检查HTTP请求是否成功(状态码200-299) if (!peticion.ok) { throw new Error(`HTTP错误!状态码:${peticion.status}`); } let resultado = await peticion.json(); // 调用结果处理函数,传入解析后的JSON数据 handleResult(resultado); } catch (error) { console.error('请求出错:', error); // 可在此添加用户可见的错误提示逻辑 } }; // 抽离结果处理逻辑,更清晰易维护 const handleResult = (oreen) => { switch (oreen.enviando) { case -1: chenille++; document.getElementById("div1").innerHTML += oreen.cat + "<br />"; updateProgress(chenille, leray.length); tvmit_wrongUp(); break; case 1: chenille++; document.getElementById("div1").innerHTML += oreen.dog + "<br />"; updateProgress(chenille, leray.length); tvmit_wrongUp(); break; case 2: chenille++; document.getElementById("div2").innerHTML += oreen.sky + "<br />"; nieva++; updateProgress(chenille, leray.length); tvmit_dieUp(); break; case 3: chenille++; document.getElementById("div3").innerHTML += oreen.water + "<br />"; tvmit_liveUp(); updateProgress(chenille, leray.length); break; } OKTY(leray, chenille, aarsh, nieva); // 模仿原jQuery的循环逻辑:如果还有未处理的行,继续发起请求 if (chenille < leray.length) { envSoli(); } }; // 启动第一个请求 envSoli();
关键修改点说明:
- 补充
beforeSend逻辑:添加updateCheckStatus函数,实现原jQuery在请求发起前更新状态元素的功能; - 调用结果处理函数:不再定义函数却不执行,确保获取到JSON后立即处理HTML更新;
- 增加HTTP状态检查:避免请求失败时静默报错,方便排查服务器端问题;
- 实现循环请求:在处理完当前请求后,判断
chenille是否小于总行数,若是则再次调用envSoli(),实现逐行发送请求的效果; - 修正HTML追加方式:原生
append方法传字符串会变成纯文本节点,改用innerHTML +=实现和jQueryappend一致的HTML追加效果。
内容的提问来源于stack exchange,提问作者SadDeepLoper
相关产品推荐
相关产品推荐

