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

Google Distance Matrix API返回结果顺序错乱问题求助

解决Google Distance Matrix API结果顺序错乱&批量处理问题

看起来你遇到的核心问题是异步请求的无序性——因为Distance Matrix API的回调是异步触发的,先发送的请求不一定先返回,所以输出顺序会乱;另外批量处理5500条数据也需要考虑API配额和请求限流的问题。我来帮你一步步修复这些问题:

现有代码的关键问题

  • 回调函数没有绑定对应的id(每条数据的唯一标识),回调返回时无法对应到原始请求数据
  • 异步请求没有并发控制,一次性发送大量请求容易触发API限流,也会加剧顺序错乱
  • 只处理了DRIVING一种交通方式,没实现你需要的多方式查询
  • 错误处理过于简陋,没有重试机制,容易丢失数据

优化后的解决方案

我会用Promise封装API调用,结合async/await控制请求流程,同时给每个请求绑定原始数据标识,确保结果和输入一一对应:

1. 重构CSV解析逻辑

先简化CSV读取和解析,把每条数据转换成结构化对象,方便后续处理:

// 假设CSV第一行是表头,先过滤空行并跳过表头
const rows = data.split(/\r?\n|\r/).filter(row => row.trim() !== '');
const employeeData = rows.slice(1).map(row => {
  const cells = row.split(',');
  return {
    id: cells[0],
    origin: {
      lat: parseFloat(cells[1]),
      lng: parseFloat(cells[2])
    },
    destination: {
      lat: parseFloat(cells[4]),
      lng: parseFloat(cells[5])
    }
  };
});

2. 用Promise封装API调用

把API请求封装成Promise,传递id和交通方式参数,方便后续关联结果:

function getTravelTime(origin, destination, travelMode, id) {
  return new Promise((resolve, reject) => {
    const service = new google.maps.DistanceMatrixService();
    service.getDistanceMatrix({
      origins: [origin],
      destinations: [destination],
      travelMode: travelMode,
      avoidHighways: false, // 可按需调整
      avoidTolls: false     // 可按需调整
    }, (response, status) => {
      if (status === 'OK') {
        const element = response.rows[0].elements[0];
        if (element.status === 'OK') {
          resolve({
            id: id,
            travelMode: travelMode,
            duration: element.duration.text,
            durationValue: element.duration.value, // 数值型时长,方便后续计算
            distance: element.distance.text,
            distanceValue: element.distance.value
          });
        } else {
          reject(new Error(`查询失败:${element.status} (ID: ${id})`));
        }
      } else {
        reject(new Error(`API请求失败:${status} (ID: ${id})`));
      }
    });
  });
}

3. 批量并发处理请求(控制并发数)

5500条数据不能一次性全部发送,我们控制并发数(比如同时发10个请求),最后按id排序确保结果顺序和输入一致:

// 批量处理工具函数:控制并发数,避免限流
async function processBatch(items, batchSize, handler) {
  const results = [];
  for (let i = 0; i < items.length; i += batchSize) {
    const batch = items.slice(i, i + batchSize);
    const batchResults = await Promise.all(batch.map(item => handler(item)));
    results.push(...batchResults);
  }
  // 按id排序,保证结果和原始输入顺序一致
  return results.sort((a, b) => a.id.localeCompare(b.id));
}

// 主处理函数
async function processAllData() {
  // 定义需要查询的交通方式
  const travelModes = ['DRIVING', 'WALKING', 'BICYCLING', 'TRANSIT'];
  const allResults = [];

  for (const mode of travelModes) {
    console.log(`正在处理${mode}类型的请求...`);
    const modeResults = await processBatch(employeeData, 10, async (item) => {
      try {
        return await getTravelTime(item.origin, item.destination, mode, item.id);
      } catch (error) {
        console.error(error.message);
        // 错误时返回标记数据,避免中断整个流程
        return { id: item.id, travelMode: mode, error: error.message };
      }
    });
    allResults.push(...modeResults);
  }

  // 渲染结果到页面表格
  renderResultsTable(allResults);
}

// 渲染结果表格
function renderResultsTable(results) {
  let tableHtml = `
    <table class="table table-bordered table-striped">
      <thead>
        <tr>
          <th>ID</th>
          <th>交通方式</th>
          <th>行程时间</th>
          <th>行程距离</th>
          <th>状态</th>
        </tr>
      </thead>
      <tbody>
  `;
  
  results.forEach(result => {
    tableHtml += `
      <tr>
        <td>${result.id}</td>
        <td>${result.travelMode}</td>
        <td>${result.duration || 'N/A'}</td>
        <td>${result.distance || 'N/A'}</td>
        <td>${result.error ? '失败' : '成功'}</td>
      </tr>
    `;
  });
  
  tableHtml += '</tbody></table>';
  // 将表格插入到页面指定元素,比如:
  // document.getElementById('results-container').innerHTML = tableHtml;
  console.log('所有数据处理完成!');
}

// 启动处理流程
processAllData();

额外注意事项

  • API配额与限流:高级账户配额更高,但batchSize建议设为10-20之间;如果遇到OVER_QUERY_LIMIT错误,可以在getTravelTime中添加重试逻辑(比如最多重试3次,每次间隔1秒)
  • 结果一致性:同一坐标对结果偶尔不一致可能是实时路况影响,可添加departureTime参数(设置为当前时间或指定时间)获取更稳定的结果
  • CSV格式兼容性:如果CSV有复杂格式(比如带引号的字段),建议用专门的CSV解析库(如PapaParse)处理,避免手动拆分出错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:48:27