等待操作结束,然后继续执行代码

时间:2019-05-05 14:03:09

标签: javascript reactjs ecmascript-6 highcharts async-await

我解释一下我的情况:

我正在使用HighCharts地图。代码强制执行DrillDown(强制更改地图),完成该操作后,我必须在此新地图的所有点内进行搜索(注意DrillDown -doDrilldown()`不是我声明的函数,而是一个函数)属性的属性)

问题在于,我必须等到DrillDown结束后才能搜索此新加载的地图的所有点。我已经使用SetTimeOut函数解决了它:

var names = name.split(', ');

// Find point in countries map
this.internalChart.series[0].data.forEach(data => {
    if (data.name === names[1]) {
      data.doDrilldown() // FORCE DRILLDOWN. HERE I MUST WAIT
      // WAITING WITH A TIMEOUT IS WORKING
      setTimeout(() => {
        // CODE THAT MUST BE EXECUTED ONCE MAP IS LOADED
        this.state.loadedMaps.length > 0 && this.internalChart.options.drilldown.series[0].data.forEach(dataInside => {
          if (dataInside.name === names[0]) {
            this.setState({
              province: dataInside['hc-key'],
              loading: false
            });
          }
        });
      }, 1000)
    }
});

但这不是正确的方法。我不想总是等待一秒钟,我希望代码在加载完成后立即执行。我尝试使用异步/等待,但无法正常工作。我尝试过的代码是:

var names = name.split(', ');

// Find point in countries map
this.internalChart.series[0].data.forEach(data => {
    if (data.name === names[1]) {
        (async () => { await data.doDrilldown(); })() //HERE I MUST WAIT FOR DO THIS ACTION
            .then(()=>{
                // ONCE DONE BELOW ACTION, EXECUTE NEXT CODE:
                this.internalChart.options.drilldown.series[0].data.forEach(dataInside => {
                    if (dataInside.name === names[0]) {
                        this.setState({
                            //country: country,
                            province: dataInside['hc-key'],
                            loading: false
                        });
                    }
                });
            });
    }
});

任何人都知道我该如何解决我的问题?

谢谢。


编辑1:

我举了一个代表问题的例子。可以在这里找到:JSFiddle example


编辑2:

我需要知道.doDrilldown()何时完成。此函数将加载新的地图及其数据,因此当加载新的地图和新数据时,代码应继续执行。我正在加载新的向下钻取系列,例如:

// Import all map data
import(`./maps/${point['hc-key']}-all.geo`).then(mapData => {

  // Set data of the map
  var data = [];
  mapData.default.features.forEach((element, i) => {
    data.push({ 'hc-key': element.properties['hc-key'], 'name': element.properties.name, 'value': 0 });
  });

  // Create the new drilldown serie
  try {
    var drilldownSerie = {
      id: point['hc-key'],
      mapData: mapData.default,
      data: data,
      joinBy: 'hc-key',
      name: mapData.default.title,
      allowPointSelect: true,
      borderColor: '#ffffff',
      borderWidth: 1.2,
      states: {
        hover: {
          color: this.props.geoColor
        },
        select: {
          color: this.props.geoColor
        }
      },
      dataLabels: {
        enabled: true,
        format: '{point.name}'
      },
      point: {
        events: {
          click: (event) => {
            this.props.handleZoneChange(event.point);

            this.setState({
              selectedPoint: event.point
            });

            console.log("Click")
            console.log(this.state.selectedPoint)
            console.log("---")

          }
        }
      }
    };

    // Add the new drilldown serie
    this.internalChart.addSeriesAsDrilldown(point, drilldownSerie);

  } catch (err) {
    console.log(err.message)
  }
}).catch((err) => {
  console.log(err.message)
})

编辑3:

如果需要的话,这里是完整的代码。

import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import Highcharts from 'highcharts'
import HC_map from 'highcharts/modules/map'; //module
import HC_drilldown from 'highcharts/modules/drilldown'; //module
import HighchartsReact from 'highcharts-react-official';
import Button from '@material-ui/core/Button';
import worldMap, { dataWorldMap } from "./maps/worldMap.js";

HC_map(Highcharts); //init module
HC_drilldown(Highcharts) //init module

Highcharts.setOptions({
lang: {
    drillUpText: '◁ Volver a: {series.name}'
}
});

class GeoZoneChart extends Component {

constructor(props) {
    super(props);

    this.state = {
    loading: false,
    selectedPoint: ''
    };
}

geoZoneOptions = {
    chart: {
    map: worldMap,
    events: {
        drilldown: (event) => {
        this.handleMapChange(event.point);
        },
        drillup: (event) => {

        setTimeout(() => {
            console.log("DU")
            console.log(this.state.selectedPoint)
            console.log("---")
        }, 1000)

        },
    }
    },
    title: {
    text: ""
    },
    mapNavigation: {
    enabled: true,
    buttonOptions: {
        verticalAlign: 'bottom'
    }
    },
    colorAxis: {
    min: 0,
    max: 0,
    minColor: "#f7f7f7",
    maxColor: "#e2e2e2"
    },
    tooltip: {
    enabled: false
    },
    legend: {
    enabled: false
    },
    exporting: { enabled: false },
    series: [{
    mapData: worldMap,
    data: dataWorldMap,
    joinBy: 'hc-key',
    name: 'Mundo',
    allowPointSelect: true,
    borderColor: '#ffffff',
    borderWidth: 1.2,
    states: {
        hover: {
        color: this.props.geoColor
        },
        select: {
        color: this.props.geoColor
        }
    },
    dataLabels: {
        enabled: true,
        format: '{point.name}'
    },
    }, {
    name: 'Separators',
    type: 'mapline',
    color: 'silver',
    showInLegend: false,
    enableMouseTracking: false
    }],
    drilldown: {
    activeDataLabelStyle: {
        textDecoration: 'none',
        color: 'black'
    },
    series: []
    }
}

internalChart = undefined;

handleMapChange = (point) => {

    // Import all map data
    import(`./maps/${point['hc-key']}-all.geo`).then(mapData => {

    // Set data of the map
    var data = [];
    mapData.default.features.forEach((element, i) => {
        data.push({ 'hc-key': element.properties['hc-key'], 'name': element.properties.name, 'value': 0 });
    });

    // Create the new drilldown serie
    try {
        var drilldownSerie = {
        id: point['hc-key'],
        mapData: mapData.default,
        data: data,
        joinBy: 'hc-key',
        name: mapData.default.title,
        allowPointSelect: true,
        borderColor: '#ffffff',
        borderWidth: 1.2,
        states: {
            hover: {
            color: this.props.geoColor
            },
            select: {
            color: this.props.geoColor
            }
        },
        dataLabels: {
            enabled: true,
            format: '{point.name}'
        },
        point: {
            events: {
            click: (event) => {
                this.props.handleZoneChange(event.point);

                this.setState({
                selectedPoint: event.point
                });

                console.log("Click")
                console.log(this.state.selectedPoint)
                console.log("---")

            }
            }
        }
        };

        // Add the new drilldown serie
        this.internalChart.addSeriesAsDrilldown(point, drilldownSerie);

        // Select all map 
        //this.selectAll();
    } catch (err) {
        console.log(err.message)
    }
    }).catch((err) => {
    console.log(err.message)
    })
}

componentDidMount = () => {
    // Recover and set selected zone if exist
    this.props.defaultZone && this.selectRegionByName(this.props.defaultZone)
}

selectRegionByName = (name) => {
    if (!name.includes(', ')) {
    // Find point in global map
    this.internalChart.series[0].data.forEach(data => {
        if (data.name === name) {
        // Select the point 
        data.select(true, true)
        }
    });
    } else {
    var names = name.split(', ');
    // Find point in countries map
    this.internalChart.series[0].data.forEach(data => {
        if (data.name === names[1]) {
        // Drilldown on the map
        data.doDrilldown();
        setTimeout(() => {
            this.internalChart.series[0].data.forEach(dataInside => {
            if (dataInside.name === names[0]) {

                // Select the point
                dataInside.select(true, true)
            }
            });
        }, 100)
        }
    });
    }
}

afterChartCreated = (chart) => {
    this.internalChart = chart;
}

selectAll = () => {
    this.internalChart.series[0].data.forEach(data => {
    data.select(true, true);
    });

    this.props.handleSelectAllZones(this.internalChart.series[0].name);
}

componentWillUnmount = () => {
    this.internalChart.series[0].data.forEach(data => {
    data.select(false, false);
    });
}

render() {
    return (
    <Fragment>
        <HighchartsReact
        highcharts={Highcharts}
        constructorType={'mapChart'}
        options={this.geoZoneOptions}
        callback={this.afterChartCreated}
        />

        <Button
        variant="contained"
        color="primary"
        onClick={this.selectAll}
        style={{
            marginTop: -28,
            padding: 0,
            paddingLeft: 10,
            paddingRight: 10,
            float: "right",
            backgroundColor: this.props.geoColor,
            '&:hover': {
            backgroundColor: this.props.geoDarkColor
            }
        }}
        >
        Seleccionar todo
        </Button>
    </Fragment >
    );
}
}

GeoZoneChart.propTypes = {
handleZoneChange: PropTypes.func
};

export default GeoZoneChart;

编辑4:

我想实现在doDrilldown()之后执行了代码。我的问题是,当我在某个点(point.doDrilldown()上进行向下钻取时,代码会异步加载地图,但代码会继续执行(地图尚未加载)并失败(如果我不使用{{1 }})。因此,我需要等待setTimeout结束,加载异步映射结束,然后继续执行代码。

@WojciechChmiel的代码(已修改,我添加了异步负载,但它不起作用),我一直在尝试实现以下目的:

// @WojciechChmiel函数已修改   (函数(H){     H.Point.prototype.doDrilldown = function(       _holdRedraw,       类别,       originalEvent     ){       var series = this.series,         图表= series.chart,         向下钻取= chart.options.drilldown,         i =(drilldown.series || [])。length,         seriesOptions;

doDrilldown()

编辑5:

这是主要问题:

  if (!chart.ddDupes) {
    chart.ddDupes = [];
  }

  while (i-- && !seriesOptions) {
    if (
      drilldown.series[i].id === this.drilldown &&
      chart.ddDupes.indexOf(this.drilldown) === -1
    ) {
      seriesOptions = drilldown.series[i];
      chart.ddDupes.push(this.drilldown);
    }
  }

  // Fire the event. If seriesOptions is undefined, the implementer can check
  // for  seriesOptions, and call addSeriesAsDrilldown async if necessary.
  H.fireEvent(chart, 'drilldown', {
    point: this,
    seriesOptions: seriesOptions,
    category: category,
    originalEvent: originalEvent,
    points: (
      category !== undefined &&
      this.series.xAxis.getDDPoints(category).slice(0)
    )
  }, function(e) {
    var chart = e.point.series && e.point.series.chart,
      seriesOptions = e.seriesOptions;

    if (chart && seriesOptions) {
      if (_holdRedraw) {
        chart.addSingleSeriesAsDrilldown(e.point, seriesOptions);
      } else {
        chart.addSeriesAsDrilldown(e.point, seriesOptions);
      }
    }
    // My code should go here?
    else {
      console.log(e.point)
      // Import all map data
      import(`./maps/${e.point['hc-key']}-all.geo`)
      .then(mapData => {

          // Set data of the map
          var data = [];
          mapData.default.features.forEach((element, i) => {
          data.push({ 'hc-key': element.properties['hc-key'], 'name': element.properties.name, 'value': 0 });
          });

          // Create the new drilldown serie
          try {
              var drilldownSerie = {
                  id: e.point['hc-key'],
                  mapData: mapData.default,
                  data: data,
                  joinBy: 'hc-key',
                  name: mapData.default.title,
                  allowPointSelect: true,
                  borderColor: '#ffffff',
                  borderWidth: 1.2,
                  states: {
                  hover: {
                      color: this.props.geoColor
                  },
                  select: {
                      color: this.props.geoColor
                  }
                  },
                  dataLabels: {
                  enabled: true,
                  format: '{point.name}'
                  },
                  point: {
                  events: {
                      click: (event) => {
                      this.props.handleZoneChange(event.point);

                      this.setState({
                          selectedPoint: event.point['hc-key']
                      });
                      }
                  }
              }
          };

          // Add the new drilldown serie
          this.internalChart.addSeriesAsDrilldown(e.point, drilldownSerie);

          // Select all map 
          //this.selectAll();
          } catch (err) {
          console.log(err.message)
          }
      }).catch((err) => {
          console.log(err.message)
      })
    }
  });

      console.log('After drilldown');
}
})(Highcharts);

1 个答案:

答案 0 :(得分:0)

这里是H.Point.prototype.doDrilldown的包装:

(function(H) {
  H.Point.prototype.doDrilldown = function(
    _holdRedraw,
    category,
    originalEvent
  ) {
    var series = this.series,
      chart = series.chart,
      drilldown = chart.options.drilldown,
      i = (drilldown.series || []).length,
      seriesOptions;

    if (!chart.ddDupes) {
      chart.ddDupes = [];
    }

    while (i-- && !seriesOptions) {
      if (
        drilldown.series[i].id === this.drilldown &&
        chart.ddDupes.indexOf(this.drilldown) === -1
      ) {
        seriesOptions = drilldown.series[i];
        chart.ddDupes.push(this.drilldown);
      }
    }

    // Fire the event. If seriesOptions is undefined, the implementer can check
    // for  seriesOptions, and call addSeriesAsDrilldown async if necessary.
    H.fireEvent(chart, 'drilldown', {
      point: this,
      seriesOptions: seriesOptions,
      category: category,
      originalEvent: originalEvent,
      points: (
        category !== undefined &&
        this.series.xAxis.getDDPoints(category).slice(0)
      )
    }, function(e) {
      var chart = e.point.series && e.point.series.chart,
        seriesOptions = e.seriesOptions;

      if (chart && seriesOptions) {
        if (_holdRedraw) {
          chart.addSingleSeriesAsDrilldown(e.point, seriesOptions);
        } else {
          chart.addSeriesAsDrilldown(e.point, seriesOptions);
        }
      }
    });

        console.log('After drilldown');
  }
})(Highcharts);

如您所见,此功能是同步的。如果您使用它异步添加数据,请添加一个复制它的示例。