javascript - for loop to generate charts (amchart)

2020-07-28 03:04发布

问题:

Am trying to generate multiple line charts at one go using the code below. However, it isn't working. What would be the best way to generate graphs using a for/while or any other looping mechanism? I have many charts to generate.

   var db_query = Array();
    db_query[1] = <?php echo json_encode($db_query_1) ?>;
    db_query[2] = <?php echo json_encode($db_query_2) ?>;

    var chartConfig1 = clone(chartConfigLineOne);
    var chartConfig2 = clone(chartConfigLineOne);

    for(var i=1, len=2; i <= len; i++) {
        /* chart initialization */
        var chart_num = "chart" + i.toString();
        var plot_num =  "plot" + i.toString();
        var chartConfig_num = "chartConfig" + i.toString();
        /*alert(chart_num);
        alert(plot_num);
        alert(chartConfig_num);*/
        chart_num = AmCharts.makeChart(plot_num, chartConfig_num);

        $.ajax({
            type: 'POST',
            url: "query_db.php",
            data: {'db_que': db_query[i]},
            dataType: 'json',
            context: document.body,
            global: false,
            async:  true,
            success: function(data) {
                //alert(data);
                chart_num.dataProvider = data;
                chart_num.validateNow();
            }
        });
    }

UPDATED CODE

        <script type="text/javascript">

            var chartNameList = ['chart1','chart2'];
            var divId = ['plot1','plot2'];
            var configList = ['chartConfig1','chartConfig2'];
            var dbQuery = [];

            var chartConfig1 = clone(chartConfigLineOne);
            var chartConfig2 = clone(chartConfigLineOne);

             dbQuery[0] = <?php echo json_encode($db_query_1) ?>;
             dbQuery[1] = <?php echo json_encode($db_query_2) ?>;

            /* chart initialization */
            for(var i =0; i < 2; i += 1)   {
                //window["chart"+i] = createChartObj(divId[i],configList[i]);
                execDbQuery(divId[i],configList[i],dbQuery[i],chartNameList[i]);
            }
        </script>

/**
 * Execute of DB query
 */

function execDbQuery(divId, configObj, dbQuery, chartObj) {
    chartObj = AmCharts.makeChart(divId, configObj);
    $.ajax({
        type: 'POST',
        url: "query_db.php",
        data: {'db_que': dbQuery},
        dataType: 'json',
        context: document.body,
        global: false,
        async:  true,
        success: function(data) {
            //alert(data);
            chartObj.dataProvider = data;
            chartObj.validateNow();
        }
    });
} 

回答1:

As many comments correctly pointed out, you should probably start with rethinking your approach to data loading. Passing SQL queries in from client-side is asking for trouble. Will you be able to properly sanitize your queries to guard against malicious code? You can't be sure.

It's far more reasonable to move your DB access layer to PHP. You can pass in parameters needed for PHP script running on server to identify what needs to be loaded from DB and construct and execute actual SQL queries.

I.e.: query_db.php?chart_id=5

It would be up for PHP script to determine what to do. Given that you're currently using PHP to format those SQL queries, I can hardly image it can be a problem.

This brings us to another issue. Your current setup will run multiple AJAX requests simultaneously. While it's probably OK in the example you posted which has two charts, it can bog down the performance if you you have, say, 30 charts you need to load data for.

The solution would be to daisy-chain the loading. Do not start loading of another chart, until the previous one finishes loading. I.e.:

var charts = [ {
  "name": "chart1",
  "div": "plot1",
  "config": clone( chartConfigLineOne ),
  "query": <? php echo json_encode( $db_query_1 ) ?>
}, {
  "name": "chart2",
  "div": "plot2",
  "config": clone( chartConfigLineOne ),
  "query": <? php echo json_encode( $db_query_2 ) ?>
} ];

// do whatever modifications to each chart's config you need here
// ...

// function that creates the chart
function processNextChart() {
  if ( charts.length ) {
    var chart = charts.shift();
    $.ajax( {
      type: 'POST',
      url: "query_db.php",
      data: {
        'db_que': chart.query
      },
      dataType: 'json',
      context: document.body,
      global: false,
      async: true,
      success: function( data ) {
        chart.config.dataProvider = data;
        chartObj = AmCharts.makeChart( chart.div, chart.config );
        setTimeout( processNextChart, 100 );
      }
    } );
  }
}

// process first chart
processNextChart();

Please note how I simplified your whole chart array with a single array that holds all applicable data.

Please note, that the above code is not live-tested and is meant as a guiding point for your own implementation.



回答2:

Do not make ajax calls inside the for loop. It's a burden on server. The less calls you make, the more responsive is your ui. So, the better way to implement what you want is to get all data for all graphs in one ajax call and on success to iterate through the data building your graphs with AmCharts.makeChart.