JS编辑器中Async-await fetch触发重复alert弹窗问题排查
问题诱因
- 状态变量重置时机错误:
unpublished = false和files = {}是在请求发起后同步执行的,无需等待异步请求返回。所有send请求拿到响应做条件判断时,这两个变量已经满足!unpublished && !Object.keys(files).length的要求,每一个请求成功返回都会触发一次alert。 - 缺少全局请求完成统计:代码没有统计总共需要提交的请求数量,无法判断是否所有修改都已经提交完成,只要单个请求返回时满足状态条件就会触发结束逻辑。
修复方案
新增待处理请求计数器,只有所有请求全部完成后才执行结束提示、重置加载状态和修改状态的逻辑,修改后的代码如下:
const publish = () => { if (unpublished || Object.keys(files).length) { // 启动加载动画 let icon = document.getElementById("loader"); icon.innerText = 'refresh'; icon.classList.add("spin"); // 待处理请求计数器 let pendingRequests = 0; // 处理文本修改 if (unpublished) { pendingRequests++; let parcel = new FormData(); parcel.append("lang", langId); parcel.append("page", pageId); parcel.append("edits", JSON.stringify(edits)); send(parcel); } // 处理图片修改 if (Object.keys(files).length) { Object.keys(files).forEach(section => { const length = Object.keys(files[section]).length; for (let i = 0; i < length; i++) { pendingRequests++; const tag = Object.keys(files[section])[i]; const file = Object.values(files[section])[i]; let parcel = new FormData(); parcel.append("lang", langId); parcel.append("page", pageId); parcel.append("section", section); parcel.append(tag, file); send(parcel); } }) } async function send(parcel) { try { const response = await fetch("", { method: "POST", body: parcel, }); if (!response.ok) throw new Error(response.statusText); } catch (err) { alert(err.message); } finally { pendingRequests--; // 所有请求完成后再执行结束逻辑 if (pendingRequests === 0) { // 状态重置移到此处,避免请求失败时丢失未提交的修改记录 unpublished = false; files = {}; // 停止加载动画 icon.classList.remove("spin"); icon.innerText = 'save'; alert("changes published"); } } } } }
内容的提问来源于stack exchange,提问作者user16822287
相关产品推荐
相关产品推荐

