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

使用Promises或Async/Await填充表单遇值覆盖问题求助

问题根源分析

你的代码里有几个关键问题导致异步操作顺序混乱,进而出现值被覆盖的情况:

  • getJson 没有返回 Promise:虽然getFSEs标了async,但内部用的是回调式的$.ajax,并没有把异步操作包装成Promise,所以async函数会立即返回一个已resolve的Promise,不会等待ajax请求完成。
  • .then 中错误地直接执行函数:比如.then(getPersons("itemResponsible", "Select Person...")),这里会立即执行getPersons,而不是等待前一个Promise完成后再执行,导致所有请求几乎同时发起,顺序完全不可控。
  • getPunchlistItem 可能在下拉填充完成前执行:如果getPunchlistItem先完成,后续下拉填充的操作会覆盖它设置的表单值。

修复步骤

第一步:改造 getJson 使其返回 Promise

jQuery的$.ajax本身就返回Promise,我们可以直接利用这一点,去掉回调参数,让getJson返回Promise:

function getJson(endpointUrl) {
  return $.ajax({
    type: "GET",
    headers: {
      "accept": "application/json;odata=verbose",
      "content-type": "application/json;odata=verbose"
    },
    url: endpointUrl
  });
}

第二步:重构异步函数(以getFSEs为例)

去掉回调,改用async/await处理异步请求,确保函数返回的Promise在ajax完成并填充下拉后才resolve:

async function getFSEs(el, allText, filter) {
  try {
    const data = await getJson(myURL + "PunchlistTracking/_api/web/lists/getbytitle('FSEs')/items");
    myFSEs = data.d.results.map(FSE => [`${FSE.Id}`, `${FSE.Title}`, `${FSE.FSEName}`]);
    
    let output = `<option value='0' selected='selected'>${allText}</option>`;
    for (let i = 0; i < myFSEs.length; i++) {
      // 注意:原代码里用了myFSEs[i][3],但map出来的数组只有3个元素(索引0-2),这里修正为对应索引
      if ((myFSEs[i][2] == filter) || !filter) {
        output += `<option value='${myFSEs[i][0]}'>${myFSEs[i][1]} ${myFSEs[i][2]}</option>`;
      }
    }
    $(`#${el}`).html(output);
    return myFSEs;
  } catch (error) {
    logError(error);
    throw error; // 抛出错误让后续Promise链处理
  }
}

用同样的方式重构getPersons和getTypes函数,确保它们都返回正确的Promise。

第三步:正确控制异步执行顺序

方式一:链式调用(顺序执行下拉填充)

注意要在.then里传函数引用,用箭头函数包裹避免立即执行:

var myFSEs = []; var myTypes = []; var myPeople = [];

$(document).ready(function () {
  getFSEs("itemFSE", "Select FSE...")
    .then(() => getPersons("itemResponsible", "Select Person..."))
    .then(() => getTypes("itemType", "Select Type..."))
    .then(() => getPunchlistItem(myPLItemID))
    .catch(error => console.error("请求出错:", error));
});

方式二:并行执行(效率更高)

如果三个下拉填充请求不需要顺序执行,可以用Promise.all并行发起,等所有请求完成后再调用getPunchlistItem:

$(document).ready(async function () {
  try {
    // 并行执行三个下拉填充请求
    await Promise.all([
      getFSEs("itemFSE", "Select FSE..."),
      getPersons("itemResponsible", "Select Person..."),
      getTypes("itemType", "Select Type...")
    ]);
    // 所有下拉填充完成后,再设置表单值
    await getPunchlistItem(myPLItemID);
  } catch (error) {
    console.error("请求出错:", error);
  }
});

第四步:确保getPunchlistItem也是异步函数

如果getPunchlistItem也是通过ajax获取数据并设置表单,同样要改造成返回Promise的函数:

async function getPunchlistItem(itemId) {
  try {
    const data = await getJson(myURL + `PunchlistTracking/_api/web/lists/getbytitle('PunchlistItems')/items(${itemId})`);
    // 设置表单值示例
    $("#itemFSE").val(data.d.FSEId);
    $("#itemResponsible").val(data.d.ResponsibleId);
    $("#itemType").val(data.d.TypeId);
    return data.d;
  } catch (error) {
    logError(error);
    throw error;
  }
}

修复原理

通过上述改造,我们确保了所有下拉框的填充操作都完成后,才执行getPunchlistItem设置表单值,这样后续就不会有异步操作覆盖已经设置好的值。同时,所有异步操作都通过Promise正确管理,执行顺序完全可控。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:00:35