为什么 jqPlot 会显示一个错误的饼图,其中包含通过 AJAX 检索到的数据?

Why does jqPlot show an erroroneous pie chart with data retrieved via AJAX?

我正在开发一个应用程序,我在其中使用 jqPlot 使用通过 AJAX 检索到的一些数据绘制饼图。但是,我注意到生成的饼图是错误的。 当我手动将数据放入数组时,饼图是正确的。

这是我的代码的一部分。

  $.ajax({
    url:'http://localhost/mijson.php',
    dataType:'json',
    async:false,
    success:function(data){
        for(a in data){
            var div_pintar = "<div id='divgrafica"+a+"' class='myChart'></div>";
            $("#espacio_graficas").append(div_pintar);
            var datos_tmp = [];
            datos_tmp.push(['Ok',data[a]['ok']]);
            datos_tmp.push(['Fail',data[a]['fail']]);

            $.jqplot('divgrafica'+a, [datos_tmp], {
                title:data[a]['label'] ,
                seriesDefaults:{
                    renderer:$.jqplot.PieRenderer,
                    trendline:{ show: true },
                },
                legend:{ show: true }
            });
            ...

我得到的JSON是这样的:

[{"label":"FECHA","requer":56,"ok":28,"fail":28},
 {"label":"TTM Y FECHA","requer":35,"ok":8,"fail":27}]

总而言之,它显示了一个饼图,例如,有两个值,但 add 是 14%。

如果我使用 ajaxDataRenderer:

也会发生同样的情况
...
    plo12 = $.jqplot('pieChart2', jsonurl,{
        title: 'AJAX JSON Data Renderer',
        dataRenderer: ajaxDataRenderer,
        seriesDefaults: {
            renderer: $.jqplot.PieRenderer,
            rendererOptions: {
                showDataLabels: true
            }
        },
        legend: { show: true, location: 'e' }
    });
    ...

没有更多信息,很难确定您的问题到底是什么。

然而,导致错误图表的最明显的事情是使用:

for(a in data){

解析 JSON object, which is actually an array,已由 AJAX success:function:

返回
$.ajax({
    success:function(data){

引用"for...in" page on MDN

Array iteration and for...in
Note: for..in should not be used to iterate over an Array where index order is important.

Array indexes are just enumerable properties with integer names and are otherwise identical to general Object properties. There is no guarantee that for...in will return the indexes in any particular order and it will return all enumerable properties, including those with non–integer names and those that are inherited.

Because the order of iteration is implementation dependent, iterating over an array may not visit elements in a consistent order. Therefore it is better to use a for loop with a numeric index (or Array.forEach or the for...of loop) when iterating over arrays where the order of access is important.

在这种情况下顺序很重要,因为无论使用何种浏览器,您都应该希望图表的显示顺序相同。因此,您应该以确定性的方式处理数组的成员。

更重要的是:

Iterating over own properties only

If you only want to consider properties attached to the object itself, and not its prototypes, use getOwnPropertyNames or perform a hasOwnProperty check (propertyIsEnumerable can also be used). Alternatively, if you know there won't be any outside code interference, you can extend built-in prototypes with a check method.

每个数组都有与其原型关联的属性,而不仅仅是数组的成员。在您的处理中包括这些,通过使用 for(a in data){},没有任何限制,几乎肯定会导致错误显示。

另一种对现有代码进行编码的方法是使用 forEach():

  $.ajax({
    url:'http://localhost/mijson.php',
    dataType:'json',
    async:false,
    success:function(data){
        data.forEach(function(curObject, a) {
            var div_pintar = "<div id='divgrafica"+a+"' class='myChart'></div>";
            $("#espacio_graficas").append(div_pintar);
            var datos_tmp = [];
            datos_tmp.push(['Ok',data[a]['ok']]);
            datos_tmp.push(['Fail',data[a]['fail']]);

            $.jqplot('divgrafica'+a, [datos_tmp], {
                title:data[a]['label'] ,
                seriesDefaults:{
                    renderer:$.jqplot.PieRenderer,
                    trendline:{ show: true },
                },
                legend:{ show: true }
            });
            ...

注意:我通常会将所有 data[a] 引用更改为 curObject,但不这样做会起作用(数组索引作为 a 传入)并导致对您的代码进行最少的更改。由于不必多次执行数组查找,进行额外的更改应该会使代码稍微快一些。

通过这些更改并使用更具描述性的 index 而不是 a,代码如下所示:

  $.ajax({
    url:'http://localhost/mijson.php',
    dataType:'json',
    async:false,
    success:function(data){
        data.forEach(function(curObject, index) {
            var div_pintar = "<div id='divgrafica"+index+"' class='myChart'></div>";
            $("#espacio_graficas").append(div_pintar);
            var datos_tmp = [];
            datos_tmp.push(['Ok',curObject['ok']]);
            datos_tmp.push(['Fail',curObject['fail']]);

            $.jqplot('divgrafica'+index, [datos_tmp], {
                title:curObject['label'] ,
                seriesDefaults:{
                    renderer:$.jqplot.PieRenderer,
                    trendline:{ show: true },
                },
                legend:{ show: true }
            });
            ...

感谢帮助我的Makyen,虽然他的回答很好,但错误仍然存​​在。 经过 16 个小时的尝试,我找到了解决方案,非常非常简单。

 .....
     var div_pintar = "<div id='divgrafica"+index+"' class='myChart'></div>";
                $("#espacio_graficas").append(div_pintar);
                var datos_tmp = [];
                    datos_tmp.push(['Ok',parseInt(datos[a]['ok'])]);
                    datos_tmp.push(['Fail',parseInt(datos[a]['fail'])]);
    ......

仅使用来自 javascript parseInt

的函数

希望对其他人有所帮助。 我浪费了很多时间:(