如何让JS代码等待HTTP请求完成后再执行后续函数?代码求助
问题分析与解决方案
核心问题
你的代码出现数据混乱的根本原因是全局变量污染,所有API请求共用同一批全局变量(如slotNumber、AuthStep),而异步请求的完成顺序不固定,后完成的请求会覆盖前一个请求的变量值,最终导致存入数组的数据混乱。此外还有Promise嵌套冗余、循环变量作用域等问题。
关键修改点
- 将请求相关变量改为局部变量,每个请求独立维护自己的数据集,避免互相覆盖
- 简化Promise逻辑,去掉不必要的嵌套,直接通过
Promise.all收集所有请求的结果 - 用
let声明循环变量,确保每次循环的变量作用域独立 - 每个请求处理完成后返回自身的分组数据,最终统一汇总成有序数组
修改后的代码
// 初始化数组,用于存储所有请求的分组数据 let slotFromAjax = []; const messages2 = [92578, 95157]; const table = document.getElementById("tickets_list_whlist") || null; if (!table) console.log('no table'); function makeHttpRequest(messages) { // 遍历每个ID,创建对应的请求Promise const promises = messages.map(messageId => { return new Promise((resolve, reject) => { GM.xmlHttpRequest({ method: "GET", url: `example.com/api/${messageId}`, headers: { "Content-Type": "application/json", "Origin": "https://example.com" }, onload: (response) => { if (response.status === 200) { const NewJson = JSON.parse(response.responseText); // 所有变量改为局部变量,每个请求独立持有 let slotNumber, AuthStep, UnAuthStep, AuthIssue, UnAuthIssue; let authStepColour, authIssueColour; if (NewJson.collection[0].schemas[1] !== undefined) { slotNumber = NewJson.collection[0].slot; if (NewJson.collection[0].schemas[0].workflow === "Yes") { AuthStep = NewJson.collection[0].schemas[0].step; UnAuthStep = NewJson.collection[0].schemas[1].step; AuthIssue = NewJson.collection[0].schemas[0].issue; UnAuthIssue = NewJson.collection[0].schemas[1].issue; } if (AuthStep === "Complete") { // 处理默认值 if (UnAuthIssue === undefined) UnAuthIssue = "No issue"; if (!AuthIssue) { AuthIssue = "No Issue"; authStepColour = "green"; authIssueColour = "black"; } // 收集当前请求的分组数据 const groupData = [slotNumber, AuthStep]; resolve(groupData); } else { // 不符合条件时返回空或对应标识,避免Promise挂起 resolve(null); } } else { resolve(null); } } else { reject(new Error(`Request failed with status ${response.status}`)); } }, onerror: (error) => { reject(error); } }); }); }); // 等待所有请求完成,过滤掉null值,得到有效分组数据 return Promise.all(promises).then(results => results.filter(item => item !== null)); } function firstFunction() { console.log("Running first function"); return makeHttpRequest(messages2); } function secondFunction(data) { console.log("Running second function with data:", data); // 这里可以把data(有序的分组数组)添加到表格中 if (table) { data.forEach(group => { const row = table.insertRow(); const cell1 = row.insertCell(0); const cell2 = row.insertCell(1); cell1.textContent = group[0]; cell2.textContent = group[1]; // 如果需要颜色样式,可以在这里设置 // cell2.style.color = authStepColour; }); } return Promise.resolve(); } function thirdFunction() { console.log("Running third function"); } // 按顺序执行函数 firstFunction() .then(secondFunction) .then(thirdFunction) .catch(error => { console.error("Error:", error); });
说明
- 每个API请求的变量都放在请求回调内部,确保各自独立,不会被其他请求覆盖
Promise.all会按请求发起的顺序返回所有结果,过滤掉无效数据后得到有序的分组数组- 在
secondFunction中可以直接使用返回的有序数组,安全地将数据添加到表格中 - 去掉了冗余的全局变量和Promise嵌套,代码逻辑更清晰
内容的提问来源于stack exchange,提问作者Bangorsteve
相关产品推荐
相关产品推荐

