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

如何让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);
  });

说明

  1. 每个API请求的变量都放在请求回调内部,确保各自独立,不会被其他请求覆盖
  2. Promise.all会按请求发起的顺序返回所有结果,过滤掉无效数据后得到有序的分组数组
  3. 在secondFunction中可以直接使用返回的有序数组,安全地将数据添加到表格中
  4. 去掉了冗余的全局变量和Promise嵌套,代码逻辑更清晰

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 02:07:14