代码之家  ›  专栏  ›  技术社区  ›  JuMoGar

在继续执行代码之前等待操作结束

  •  0
  • JuMoGar  · 技术社区  · 5 年前

    我解释我的情况:

    我在用海图地图。代码强制向下搜索(强制更改映射),完成后,我必须搜索此新映射的所有点(注意drilldown-dodrilldown()`-不是我声明的函数,而是highcharts的函数属性)

    问题是,在搜索这个新加载的地图的所有点之前,我必须等到钻取结束。我已经用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)
        }
    });
    

    但这不是正确的方法。我不希望总是等待一秒钟,我希望代码在加载完成后执行。我试过使用async/await,但它不起作用。我试过的代码是:

    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() )代码异步加载映射,但代码继续执行(映射尚未加载)并失败(如果我不使用 setTimeout )中。所以我需要等一下 多德里尔敦() 结束,加载异步映射结束,然后继续执行代码。

    @wojciechchmiel的代码(已修改,我添加了异步加载,但它不工作)我一直在尝试实现这一点:

    //@修正的wojciechchmil函数 (函数(h){ h.point.prototype.dodrilldown=函数( _保持原样, 类别, 原始喷口 ){ var系列=本系列, chart=系列图表, 钻取=chart.options.drilldown, i=(drilldown.series[])。长度, 系列选择;

      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);
    

    编辑5:

    这是主要问题:

    this.internalChart.series[0].data.forEach(data => { // FIND A POINT IN ALL MAP
        if (data.name === SelectedName1) { // IF A POINT IS FOUND...
            data.doDrilldown() // DRILLDOWN TO CHILD MAP
            // HERE I MUST WAIT. WHEN DODRILLDOWN ENDS, CONTINUE WITH BELOW CODE
            // UNDERSTANDING "ENDS" WHEN NEW MAP AND ITS DATA IS LOADED AND READY
            this.internalChart.options.drilldown.series[0].data.forEach(dataInside => { // FOR EACH POINT OF NEW MAP (DRILLDOWN/CHILD MAP)
                if (dataInside.name === SelectedName2) { // IF A POINT IS FOUND
                    this.setState({ province: dataInside['hc-key'] }); // CHANGE STATE
                }
            });
        }
    });
    
    0 回复  |  直到 5 年前
        1
  •  0
  •   Wojciech Chmiel    5 年前

    这是包装纸 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);
    

    正如你所看到的,这个函数是同步的。如果您使用它来异步添加数据,请添加一个复制它的示例。