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

使用Fetch API发起多请求未异步执行 请求pending排队阻塞问题

问题成因

你观测到的9个请求总耗时约1分钟、控制台全部显示pending、没有实现异步并发效果,核心原因有两个:

  • 后端PHP Session排他锁阻塞(核心原因):PHP默认以文件形式存储Session,调用session_start()时会自动给当前用户的Session文件加排他锁,直到请求执行结束才会释放。锁持有期间,同个客户端发起的所有携带相同Session ID的请求都会在后端排队等待锁,根本不会进入业务逻辑执行。这种完全串行的执行模式下,9个单耗时6秒的请求总时长刚好是9*6=54秒,和你观测到的1分钟耗时完全吻合。如果只是浏览器端的并发限制,总耗时应该在12秒左右(同域名HTTP/1.1默认最大6个并发,分两批执行),不会达到1分钟级别。
  • 浏览器同域名并发连接限制:HTTP/1.1协议下,浏览器针对单个域名默认最多同时建立6个TCP连接发送请求,超出数量的请求会在浏览器端排队等待连接释放,即使解决了后端锁问题,9个请求也会分两批发送,不会做到完全并行。
代码存在的显性问题
  • 变量拼写错误:代码中fetch配置的body字段传入的是foormData,和函数入参formData相比多写了一个字母o,会直接触发引用错误,属于笔误。
  • 无意义的async标记:给$.each的回调函数加了async关键字,但回调内部没有任何await逻辑,这个写法没有实际作用,还会导致fetch抛出的请求异常无法被外层捕获。
修复方案
  • 后端锁问题修复:在/api/execute.php中,读取完Session内需要的数据后,立刻调用session_write_close()手动释放Session锁,不要等请求全部执行完再释放,这样后续请求就不会在后端排队:
<?php
session_start();
// 读取业务需要的Session数据
$currentUser = $_SESSION['user'];
// 读完立刻释放锁,不阻塞其他同Session请求
session_write_close();

// 后续执行耗时的设备指令下发逻辑
  • 前端代码修正:修复笔误,替换无意义的循环写法,加上异常捕获:
async function getExecuteOutput(devices, formData) {
    const requestList = devices.map(() => {
        return fetch('/api/execute.php', {
            method: 'POST',
            body: formData // 修正之前的foormData拼写错误
        })
        .then(resp => resp.json())
        .then(res => console.log('指令执行结果', res))
        .catch(err => console.error('指令下发失败', err))
    })

    // 如果需要等所有指令都下发完成再执行后续逻辑,放开下面这行注释即可
    // await Promise.all(requestList)
}
  • 可选优化:给服务端开启HTTP/2支持,利用多路复用特性突破HTTP/1.1下的同域名并发连接数限制,进一步减少请求排队概率。
现象参考截图

请求耗时统计截图
控制台请求pending状态截图

内容的提问来源于stack exchange,提问作者Mentle Storier

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 05:48:42