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

POST不同JSON内容时Fetch请求6次后失败的问题求助

交替点击按钮6次后Fetch API出现pending及报错问题

我通过Fetch API向Node.js服务器POST包含{pageNumber, UsersPerPage}的JSON来获取用户列表,页面有两个按钮,点击时会将自身文本作为pageNumber发送POST请求,但交替点击6次后,Fetch API抛出错误:Uncaught (in promise) TypeError: Failed to fetch at HTMLDivElement.,且后续请求在网络面板显示为pending,无法完成。前5次请求均正常,已尝试设置Access-Control-Allow-Origin、no-cors头,以及使用async/await,问题仍存在。

前端代码

side1.addEventListener('click',()=>{
    fetch('/api/users/stats/side1/post',{  
       method:'POST',
       headers:{'Content-Type':'application/json'},
       body:JSON.stringify({
        pageNum:side1.textContent,
        userPerPage:userPerSide
       })
    
    });
    fetch('/api/users/stats/side1/get').then(x=>x.text()).then(Txt=>{
    display.innerHTML=Txt;
    });
});
side2.addEventListener('click', ()=>{
    fetch('/api/users/stats/side2/post',{
       method:'POST' ,
       headers:{'Content-Type':'application/json'},
       body:JSON.stringify({
        pageNum:side2.textContent,
        userPerPage:userPerSide
       })
    
    });  
    fetch('/api/users/stats/side2/get').then(x=>x.text()).then(Txt=>{
        display.innerHTML=Txt;
        });  
});

后端代码

var retVal; 
app.post('/api/users/stats/side1/post',(req,res)=>{
if(req.body){
const {pageNum,userPerPage}=req.body;
retVal=GetPage(Number(pageNum),Number(userPerPage));
}
});
app.post('/api/users/stats/side2/post',(req,res)=>{
    if(req.body){
    const {pageNum,userPerPage}=req.body;
    retVal=GetPage(Number(pageNum),Number(userPerPage));
    }
});
app.get('/api/users/stats/side1/get',(req,res)=>{
res.setHeader('content-type', 'text/plain');
res.send(retVal);
});
app.get('/api/users/stats/side2/get',(req,res)=>{
res.setHeader('content-type', 'text/plain');
res.send(retVal);
});

问题分析与解决方案

核心问题1:POST请求未响应导致连接耗尽

后端的POST接口没有向客户端返回任何响应(res.send/res.end),浏览器会一直等待服务器响应,TCP连接无法释放。浏览器对同一域名的并发连接数有限制(通常是6个),当积累到6个未关闭的连接后,新的请求就会进入pending状态,最终触发Failed to fetch错误。

修复:给POST接口添加响应
修改后端POST路由,处理完逻辑后返回响应:

app.post('/api/users/stats/side1/post',(req,res)=>{
if(req.body){
const {pageNum,userPerPage}=req.body;
retVal=GetPage(Number(pageNum),Number(userPerPage));
res.status(200).send('ok'); // 添加响应
} else {
res.status(400).send('invalid data'); // 处理异常情况
}
});
app.post('/api/users/stats/side2/post',(req,res)=>{
    if(req.body){
    const {pageNum,userPerPage}=req.body;
    retVal=GetPage(Number(pageNum),Number(userPerPage));
    res.status(200).send('ok'); // 添加响应
    } else {
    res.status(400).send('invalid data');
    }
});

核心问题2:POST与GET请求无顺序保证

当前代码中POST和GET是并行发送的,可能出现GET请求先于POST完成,导致获取到的retVal还是旧值。需要保证POST完成后再发送GET请求。

修复:用async/await保证请求顺序
修改前端点击事件:

side1.addEventListener('click', async ()=>{
    // 先等待POST请求完成
    await fetch('/api/users/stats/side1/post',{  
       method:'POST',
       headers:{'Content-Type':'application/json'},
       body:JSON.stringify({
        pageNum:side1.textContent,
        userPerPage:userPerSide
       })
    });
    // 再发送GET请求
    const response = await fetch('/api/users/stats/side1/get');
    const Txt = await response.text();
    display.innerHTML=Txt;
});
side2.addEventListener('click', async ()=>{
    await fetch('/api/users/stats/side2/post',{
       method:'POST' ,
       headers:{'Content-Type':'application/json'},
       body:JSON.stringify({
        pageNum:side2.textContent,
        userPerPage:userPerSide
       })
    });  
    const response = await fetch('/api/users/stats/side2/get');
    const Txt = await response.text();
    display.innerHTML=Txt;
});

额外优化:解决全局变量retVal的并发风险

多个请求同时修改全局变量retVal会导致数据错乱,比如快速点击两个按钮时,后一个POST会覆盖前一个的结果,GET拿到错误数据。可以简化流程,让POST直接返回处理后的结果:

后端优化:POST直接返回结果

app.post('/api/users/stats/side1',(req,res)=>{
if(req.body){
const {pageNum,userPerPage}=req.body;
const result = GetPage(Number(pageNum),Number(userPerPage));
res.setHeader('content-type', 'text/plain');
res.send(result);
} else {
res.status(400).send('invalid data');
}
});
app.post('/api/users/stats/side2',(req,res)=>{
    if(req.body){
    const {pageNum,userPerPage}=req.body;
    const result = GetPage(Number(pageNum),Number(userPerPage));
    res.setHeader('content-type', 'text/plain');
    res.send(result);
    } else {
    res.status(400).send('invalid data');
    }
});

前端对应修改:只发送一次POST请求

side1.addEventListener('click', async ()=>{
    const response = await fetch('/api/users/stats/side1',{  
       method:'POST',
       headers:{'Content-Type':'application/json'},
       body:JSON.stringify({
        pageNum:side1.textContent,
        userPerPage:userPerSide
       })
    });
    const Txt = await response.text();
    display.innerHTML=Txt;
});
side2.addEventListener('click', async ()=>{
    const response = await fetch('/api/users/stats/side2',{
       method:'POST' ,
       headers:{'Content-Type':'application/json'},
       body:JSON.stringify({
        pageNum:side2.textContent,
        userPerPage:userPerSide
       })
    });  
    const Txt = await response.text();
    display.innerHTML=Txt;
});

内容的提问来源于stack exchange,提问作者Bell Flo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 09:00:05