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

MapBox创建实时跟随轨迹线触发重复source ID报错如何解决?

Mapbox 重复ID报错修复方案

根因说明

错误Error: There is already a source with this ID产生的核心原因是:你在500ms一次的轮询逻辑中,每次调用targetTrackingLine都会重复执行addSource和addLayer注册ID为trace的数据源和图层,Mapbox 不允许同一ID的资源重复注册,直接抛出异常,而async函数内的异常未被捕获就会触发Unhandled Promise Rejection报错。
同时你的代码存在两个额外隐患:

  • 每次调用targetTrackingLine都会生成一个新的10ms定时器,没有清理逻辑,会导致定时器泄漏
  • 轨迹坐标没有全局维护,每次调用都会重置轨迹数据,无法累积历史轨迹点

修复步骤

1. 调整初始化逻辑,仅注册一次轨迹资源

把trace数据源和图层的注册逻辑放到地图加载完成的回调中,只执行一次,同时组件卸载时清理资源避免内存泄漏:

data() {
  return {
    // 新增全局变量维护轨迹坐标和轮询定时器
    traceCoordinates: [],
    locationTimer: null
  }
},
mounted() {
  this.createMap();
  // 地图加载完成后初始化轨迹资源
  this.map.on('load', () => {
    // 注册前先判断是否已存在,避免重复注册
    if (!this.map.getSource('trace')) {
      this.map.addSource('trace', {
        type: 'geojson',
        data: {
          type: 'Feature',
          properties: {},
          geometry: {
            type: 'LineString',
            coordinates: []
          }
        }
      });
    }
    if (!this.map.getLayer('trace')) {
      this.map.addLayer({
        'id': 'trace',
        'type': 'line',
        'source': 'trace',
        'paint': {
          'line-color': '#000',
          'line-width': 4
        }
      });
    }
    // 启动位置轮询
    this.locationTimer = setInterval(() => {
      this.getLocation()
    }, 500)
  })
},
// 组件卸载时清理所有资源
beforeDestroy() {
  // 清理位置轮询定时器
  clearInterval(this.locationTimer)
  // 清理地图资源
  if (this.map) {
    if (this.map.getLayer('trace')) this.map.removeLayer('trace')
    if (this.map.getSource('trace')) this.map.removeSource('trace')
  }
}

2. 重构targetTrackingLine逻辑,仅更新轨迹数据

去掉重复的资源注册逻辑,只做坐标追加和数据源更新,同时添加异常捕获处理:

async targetTrackingLine() {
  try {
    if (this.lng !== "0.000000" && this.lng !== "") {
      const response = await fetch(
          `https://api.mapbox.com/geocoding/v5/mapbox.places/${this.center}.json?access_token=${this.access_token}`
      );
      const data = await response.json();
      // 追加新坐标到全局轨迹数组
      this.traceCoordinates.push(data.query);
      // 更新地图数据源
      const traceSource = this.map.getSource('trace');
      const traceData = traceSource._data;
      traceData.geometry.coordinates = this.traceCoordinates;
      traceSource.setData(traceData);
    }
  } catch (err) {
    console.error('轨迹更新失败', err)
  }
}

额外优化点

你当前的getLocation函数中同时用了axios和fetch请求两次Mapbox逆地理编码接口,属于重复请求,可以合并成一次请求减少API调用次数,降低触发接口限流的概率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 11:00:02