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

多次并发调用POST方法出现数据覆盖及异步函数执行顺序疑问

核心原理答疑

1. 运行中的异步函数是否会被中断?

JS是单线程事件循环模型,同步代码执行时绝对不会被打断,只有当前调用栈所有同步代码全部执行完毕、调用栈为空时,才会依次读取微任务队列、宏任务队列的待执行任务运行。你代码里的printSqrt是纯同步循环,只要它开始执行,所有点击事件回调、Promise回调都会被暂存到任务队列等待,直到循环完全跑完才会被调度执行。

2. 同一个异步函数同时调用的执行顺序

async函数的执行遵循固定规则:

  • 调用async函数时,函数内第一个await之前的所有代码都是同步执行,会严格按照调用顺序在调用栈中依次运行,不会被其他代码打断
  • 遇到await关键字后,当前函数会暂停执行,await之后的代码会被封装为微任务,等待await的Promise状态变更后,再进入微任务队列排队执行

所以不存在运行中的异步函数被另一个同函数实例中断的情况,所有同步逻辑的执行顺序是完全可控的。


现有队列逻辑的问题修复

你担心的任务积压场景是真实存在的,当前代码的漏洞在于isExecuting赋值时机不对:
队列清空后,代码先执行同步的printSqrt('In queue'),此时isExecuting仍然为true,如果这个阶段用户点击按钮新增任务到队列,点击事件的判断逻辑会直接返回、不会触发executeQueue。等printSqrt执行完再把isExecuting设为false时,队列里的新任务就失去了执行触发时机,只能等下次点击才会被处理。

修复方案非常简单,调整executeQueue的执行顺序即可:

async function executeQueue() {
  while (taskQueue.length != 0) {
    const item = taskQueue.shift()
    await addToCart(item)
  }
  // 先修改执行状态,再运行其他同步逻辑
  isExecuting = false
  printSqrt('In queue')
}

调整后就算printSqrt运行期间有新任务进入队列,点击事件判断isExecuting已经为false,就会主动触发executeQueue运行,不会出现任务积压。

补充说明:你最开始遇到的加购数量小于实际点击数的问题,本质是后端并发写冲突:多个加购请求同时到达后端,同时读取当前购物车数量、各自加1后回写,就会出现数据覆盖,你用队列串行发送请求的方案刚好规避了这个并发问题,是合理的解决方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 03:36:03