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

如何使用async/await从subscribe中返回数据并执行后续操作

问题场景

父组件从后端获取数据后,过滤出包含mbl_vessels属性的条目,通过Service发送给孙组件;孙组件接收数据后需要处理并调用地图绘制相关函数,但由于RxJS订阅的异步特性,订阅外部的函数会提前执行并拿到undefined,仅订阅内部能获取到正常数据。

现有代码

Service

sendDataToMap(dataToMap: []) {
  this.send_data.next(dataToMap);
}

reciveDataToMap(): Observable<any>{
  return this.send_data.asObservable();
}

getDataToRenderOnMap(dataToMap){
  this.routesList.push(data?.mbl_vessels?.path);

  const currentPos: number[] = Object.values(data?.mbl_vessels?.currentPosition);
  this.pointsToFit.push(currentPos);

  const marker: IMarker = {
    transportType: data?.quote?.transportationMode,
    currentPosition: currentPos
  };

  this.markersToRender.push(marker);
}

return {
  routesList: this.routesList,
  pointsToFit: this.pointsToFit,
  markersToRender: this.markersToRender
};

父组件

this.elementsToMap = elementsReq.data.filter(item => item.hasOwnProperty('mbl_vessels'));
this.miniMapService.sendDataToMap(this.elementsToMap);

孙组件

ngAfterViewInit() {
  this.loadMap(MapStyles.COLOR_STYLE);
  this.loadMapControls();

  this.prepareDataToMap();

  // 期望在订阅完成后执行,但当前会提前拿到undefined
  this.setLineStyle(LinePathColor.TO_COLOR, geoData);
  this.setCustomMarkers();
  this.setMarkerForBounding(shipmentsDataPosition);

  this.cdref.detectChanges();
}

prepareDataToMap(){
  this.miniMapService.reciveDataToMap().subscribe((data) => {
    this.dataToMap = data;
    this.dataReturned = this.miniMapService.getDataToRenderOnMap(this.dataToMap);
  });
}

setLineStyle(colorPath: string, route?) {
  this.mapa.on('load', () => {
    this.mapa.addSource('route', {
      'type': 'geojson',
      'data': {
        'type': 'Feature',
        'properties': {},
        'geometry': {
          'type': 'LineString',
          'coordinates': route
        }
      }
    });

    this.mapa.addLayer({
      'id': 'route',
      'type': 'line',
      'source': 'route',
      'layout': {
        'line-join': 'round',
        'line-cap': 'round'
      },
      'paint': {
        'line-color': colorPath,
        'line-width': 2,
        "line-dasharray": [0.2, 2]
      }
    });
  });
}
解决方案

1. 修复Service数据污染问题

原Service的getDataToRenderOnMap使用类成员变量存储数据,会导致多次调用时数据累加,改用局部变量避免污染:

getDataToRenderOnMap(dataToMap){
  // 改用局部变量,避免跨调用的数据污染
  const routesList = [];
  const pointsToFit = [];
  const markersToRender = [];

  dataToMap.forEach((data) => {
    routesList.push(data?.mbl_vessels?.path);

    const currentPos: number[] = Object.values(data?.mbl_vessels?.currentPosition);
    pointsToFit.push(currentPos);

    const marker: IMarker = {
      transportType: data?.quote?.transportationMode,
      currentPosition: currentPos
    };

    markersToRender.push(marker);
  });

  return {
    routesList,
    pointsToFit,
    markersToRender
  };
}

2. 调整孙组件执行逻辑,确保数据就绪后调用地图函数

将地图相关函数的调用移至订阅内部,同时确保地图加载完成后再处理数据:

ngAfterViewInit() {
  this.loadMap(MapStyles.COLOR_STYLE);
  // 等待地图加载完成后再初始化控件和处理数据
  this.mapa.on('load', () => {
    this.loadMapControls();
    this.prepareDataToMap();
    this.cdref.detectChanges();
  });
}

prepareDataToMap(){
  this.miniMapService.reciveDataToMap().subscribe((data) => {
    this.dataToMap = data;
    this.dataReturned = this.miniMapService.getDataToRenderOnMap(this.dataToMap);
    
    // 数据处理完成后,调用地图绘制函数
    this.setLineStyle(LinePathColor.TO_COLOR, this.dataReturned.routesList);
    this.setCustomMarkers(this.dataReturned.markersToRender);
    this.setMarkerForBounding(this.dataReturned.pointsToFit);
  });
}

// 优化setLineStyle,支持批量添加路线
setLineStyle(colorPath: string, routes?: any[]) {
  if (!routes || routes.length === 0) return;
  
  routes.forEach((route, index) => {
    // 使用唯一ID避免source和layer重复
    const sourceId = `route-${index}`;
    const layerId = `route-layer-${index}`;
    
    this.mapa.addSource(sourceId, {
      'type': 'geojson',
      'data': {
        'type': 'Feature',
        'properties': {},
        'geometry': {
          'type': 'LineString',
          'coordinates': route
        }
      }
    });

    this.mapa.addLayer({
      'id': layerId,
      'type': 'line',
      'source': sourceId,
      'layout': {
        'line-join': 'round',
        'line-cap': 'round'
      },
      'paint': {
        'line-color': colorPath,
        'line-width': 2,
        "line-dasharray": [0.2, 2]
      }
    });
  });
}

关键修改说明

  • 异步逻辑对齐:将地图函数移至订阅内部,确保只有当数据接收并处理完成后才执行,解决undefined问题。
  • 地图加载时机:通过mapa.on('load')确保地图初始化完成后再处理数据,避免地图未就绪时调用API报错。
  • 数据隔离:Service改用局部变量存储处理结果,避免多次订阅时数据重复累加。
  • 批量路线支持:修改setLineStyle循环处理路线数组,适配多路线场景。

内容的提问来源于stack exchange,提问作者Pedro Miguel Pimienta Morales

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 07:50:49