簡體   English   中英

等到操作結束后再繼續執行代碼

[英]Wait until an action ends before continuing execution of code

我解釋一下我的情況:

我正在使用HighCharts地圖。 代碼強制DrillDown(強制更改地圖),一旦完成,我必須在這個新地圖的所有點內搜索(注意DrillDown -doDrilldown()` - 不是我聲明的函數,它是一個函數HighCharts的財產)

問題是我必須等到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)
    }
});

但這不是正確的方法。 我不想總是等待一秒鍾,我希望一旦加載完成就會執行代碼。 我嘗試過使用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示例


編輯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() )進行point.doDrilldown() ,代碼會加載一個地圖異步,但代碼會繼續執行(地圖尚未加載)並失敗(如果我不使用setTimeout )。 所以我需要等待doDrilldown()結束,加載異步映射結束,然后繼續執行代碼。

@WojciechChmiel的代碼(已修改,我已添加異步加載,但它無法正常工作)我一直在努力實現這一目標:

// @WojciechChmiel函數修改(函數(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);
      }
    }
    // 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
            }
        });
    }
});

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

如您所見,此功能是同步的。 如果您使用它來異步添加數據,請添加一個再現它的示例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM