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

表单首次提交时距离/时间数组为空,需同步数据并排序显示

问题分析与解决方案

我看你遇到的核心问题是异步请求时机没把控好加上数组未及时重置,导致首次提交时距离/时间数组为空,二次提交数据重复。咱们一步步拆解解决:

问题根源

  1. 异步请求的滞后性:你调用的Google Maps DistanceMatrixService是异步API,代码里刚触发getDistance就立刻把空的distance/time值push进数组了,等异步请求返回时数组早已存了空值。
  2. 数组未重置:每次提交表单时,旧的数组数据没有清空,导致二次提交时新旧数据叠加,出现重复。
  3. DOM元素获取错误:比如destInput是input元素,你用了innerText而不是value,虽然这里不影响核心功能,但也是潜在bug。

分步解决方案

1. 每次提交前重置所有数组

在表单提交或generateHTML函数开头,清空所有存储数据的数组,避免旧数据累积:

// 在generateHTML函数最开头添加
facilityArray = [];
distanceArray = [];
timeArray = [];
sortArray = [];
tempArray = [];
slicedArray = [];

2. 把异步的getDistance封装成Promise

这样我们可以等待所有距离请求完成后再处理数据,确保数组里全是有效数据:

const getDistance = (i) => {
  return new Promise((resolve, reject) => {
    const distanceService = new google.maps.DistanceMatrixService();
    distanceService.getDistanceMatrix({
      origins: [document.getElementById(`startaddress${i}`).value],
      destinations: [document.getElementById(`destaddress${i}`).value],
      travelMode: "DRIVING",
      unitSystem: google.maps.UnitSystem.IMPERIAL,
      durationInTraffic: true,
      avoidHighways: false,
      avoidTolls: false
    }, (response, status) => {
      if (status !== google.maps.DistanceMatrixStatus.OK) {
        console.log('Error:', status);
        const message = document.querySelector("#message");
        message.innerHTML = `Error: ${status}. Please resubmit.`;
        reject(status);
      } else {
        const distanceText = response.rows[0].elements[0].distance.text;
        const timeText = response.rows[0].elements[0].duration.text;
        const intDistance = parseInt(distanceText.replace(/,/g, ''));
        
        // 更新DOM显示
        document.getElementById(`distance${i}`).innerHTML = distanceText;
        document.getElementById(`time${i}`).innerHTML = timeText;
        
        // 返回整理好的数据,用于填充数组
        resolve({
          facility: document.getElementById(`startaddress${i}`).value,
          distance: distanceText,
          intDistance: intDistance,
          time: timeText
        });
      }
    });
  });
};

3. 等待所有异步请求完成后再处理数据

在创建完所有卡片后,收集所有getDistance的Promise,用Promise.all等待全部完成,再填充数组、排序并渲染Top3结果:

// 替换原循环内的getDistance调用,改为收集Promise
const distancePromises = [];
for (let i = 0; i < addresses.length; i++) {
  // ...保留原来创建卡片、设置startInput的代码
  
  // 修正destInput的获取方式(input用value而非innerText)
  destInput = document.querySelector(`#destaddress${i}`).value;
  
  // 将当前i的异步请求Promise加入数组
  distancePromises.push(getDistance(i));
}

// 等待所有距离请求完成
Promise.all(distancePromises)
  .then(results => {
    // 填充数组
    results.forEach(item => {
      facilityArray.push(item.facility);
      distanceArray.push(item.distance);
      timeArray.push(item.time);
      sortArray.push(item.intDistance);
    });
    
    // 排序并获取前3近的距离值
    sortArray.sort((a, b) => a - b);
    slicedArray = sortArray.slice(0, 3);
    
    // 找到对应的设施信息并渲染Top3区域
    const closestFacilities = results.filter(item => slicedArray.includes(item.intDistance));
    const top3Container = document.createElement('div');
    top3Container.classList.add('mt-4', 'p-3', 'bg-light', 'rounded');
    top3Container.innerHTML = `<h4>Closest 3 Service Centers</h4>`;
    
    closestFacilities.forEach(fac => {
      top3Container.innerHTML += `
        <div class="card mt-2">
          <div class="card-body">
            <h5>Service Center - ${fac.facility}</h5>
            <p>Distance: ${fac.distance} | Drive Time: ${fac.time}</p>
          </div>
        </div>
      `;
    });
    
    document.querySelector('.container-sm').appendChild(top3Container);
  })
  .catch(error => {
    console.error('部分距离请求失败:', error);
  });

4. 修正表单提交的细节

  • 重置inputVal避免重复添加地址
  • 清空旧的卡片内容,避免多次提交后页面重复渲染:
form.addEventListener("submit", (e) => {
  e.preventDefault();
  const patientAddressInput = document.querySelector("#patientaddress");
  
  // 重置inputVal,而非push
  inputVal = [patientAddressInput.value];
  
  // 清空旧卡片(保留表单)
  const container = document.querySelector(".container-sm");
  const formElement = document.querySelector("#form");
  container.innerHTML = '';
  container.appendChild(formElement);
  
  generateHTML();
});

5. 修正quickBaseQuery的作用域问题

原来的xmlHttp是在generateHTML内部创建的,外部quickBaseQuery无法访问,建议把发送请求的逻辑直接整合到generateHTML里:

const generateHTML = () => {
  const xmlHttp = new XMLHttpRequest();
  xmlHttp.open('POST', 'https://api.quickbase.com/v1/records/query', true);
  
  // ...设置请求头、onreadystatechange逻辑
  
  // 直接在这里发送请求,无需外部调用
  xmlHttp.send(JSON.stringify(body));
};

这样修改后,首次提交时会等待所有Google Maps的异步请求完成再填充数组,数组每次都会重置,不会出现空值或重复数据,同时能正确渲染出最近的3个服务中心。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 21:22:32