Альтернативы для использования цикла forEeach () при преобразовании данных для D3.js

Я все еще борюсь с этой ошибкой, как указано в этомпредыдущий пост на StackOverflow.com, Я выделил причину проблемы, которая в моем коде D3.js не может перебрать «объект». Мой источник необработанных данных - веб-интерфейс RESTful. Используя jQuery и функцию JavaScript, я могу загрузить значения в переменную с именем «набор данных». Когда я выводю содержимое набора данных как предупреждение или записываю его в элемент html, используя jQuery, все данные там. Слишком много примеров D3.js используют жестко закодированные файлы данных. Поэтому важно отметить, что когда я использую жестко запрограммированную версию одних и тех же данных, все работает, но я ограничен использованием этой динамической виртуальной переменной данных.

Когда я запускаю код, он падает в этой функции:

    dataset.forEach(function(d) {
        d.theTime = parseDate(d.theTime);
        d.theValue = +d.theValue;
    });

Сообщение об ошибкеUncaught TypeError: Cannot read property 'length' of undefined.

Когда я используюconsole.log(typeof(dataset)) прямо перед этой функцией я получаю «объект». Если есть какие-нибудь наставники D3.js, читающие это, какие у меня есть варианты для преобразования этих данных? Я исследовал несколько без успеха.

// ============= ПРИЛОЖЕНО 01 ========================

Поскольку он был запрошен здесь, это «набор данных», который можно посмотреть по ссылке предыдущего сообщения (Разбор данных временных рядов с использованием D3.js) выше:

    var dataset = [
    {'theTime': '2016/07/12 15:58:40', 'theValue': 1123.07275390625},
    {'theTime': '2016/07/12 16:21:10', 'theValue': 1055.6793212890625},
    {'theTime': '2016/07/12 16:45:40', 'theValue': 962.4850463867188},
    {'theTime': '2016/07/12 17:14:40', 'theValue': 831.2259521484375},
    {'theTime': '2016/07/12 17:55:10', 'theValue': 625.3046875}
    ];

// ============= ПРИЛОЖЕНО 02 ========================

Что касается вопроса Герардо, то переменная 'набора данных' 'загружена' (я думаю), поскольку код находится внутри функции "$ .get", которая собирает переменную "набора данных", как показано здесь:

    //~ Populate the 'dataset':
    var dataset = [];
    $.get(url, function(data){
        var itemCount = data.Items.length;
        var commaCount = itemCount - 1;
        for(i=0; i<itemCount; i++){
            if(i == commaCount){
                dataset.push("{'theTime': '" + formattedDateTime(data.Items[i].Timestamp) + "', 'theValue': " + data.Items[i].Value + "}");
            }
            else {
                dataset.push("{'theTime': '" + formattedDateTime(data.Items[i].Timestamp) + "', 'theValue': " + data.Items[i].Value + "},");
            }
        }
    //~ ALL THE D3 CODE IS INSIDE THIS '$.get' FUNCTION
    });

// ============= ПРИЛОЖЕНО 03 ========================

Я получил это работает!

Я опубликую пересмотренный рабочий код ниже. Но для любого, кто следит за этим постом, я хотел объяснить, что я нашел.

Марк предложил изменитьdataset.push() отбросить все цитаты. Это дало мне объекты вместо строк. После некоторого устранения неполадок он наконец-то отобразился, как и ожидалось (полностью взволнован!), И благодаря Марку ваши предложения сделали свое дело.

Вот пересмотренный код:

    //~ Populate the 'dataset':
    var dataset = [];
    $.get(url, function(data){
        var itemCount = data.Items.length;
        var commaCount = itemCount - 1;
        for(i=0; i<itemCount; i++){
            dataset.push({theTime: formattedDateTime(data.Items[i].Timestamp), theValue: data.Items[i].Value});
        }

        var margin = {top: 20, right: 20, bottom: 30, left: 50};
        var width = 960 - margin.left - margin.right;
        var height = 500 - margin.top - margin.bottom;
        var parseDate = d3.time.format("%Y/%m/%d %H:%M:%S").parse;

        var x = d3.time.scale()
          .range([0, width]);

        var y = d3.scale.linear()
          .range([height, 0]);

        var xAxis = d3.svg.axis()
          .scale(x)
          .orient("bottom");

        var yAxis = d3.svg.axis()
          .scale(y)
          .orient("left");

        var line = d3.svg.line()
          .x(function(d) { return x(d.theTime); })
          .y(function(d) { return y(d.theValue); });


        var svg = d3.select("#myChart").append("svg")
          .attr("width", width + margin.left + margin.right)
          .attr("height", height + margin.top + margin.bottom)
        .append("g")
          .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

        dataset.forEach(function(d) {
            d.theTime = parseDate(d.theTime);
            d.theValue = parseFloat(d.theValue);
        });

         x.domain(d3.extent(dataset, function(d) { return d.theTime; }));
         y.domain(d3.extent(dataset, function(d) { return d.theValue;}));

         svg.append("g")
                 .attr("class", "x axis")
                 .attr("transform", "translate(0," + height + ")")
                 .call(xAxis);

         svg.append("g")
                 .attr("class", "y axis")
                 .call(yAxis)
                 .append("text")
                 .attr("transform", "rotate(-90)")
                 .attr("y", 6)
                 .attr("dy", ".71em")
                 .style("text-anchor", "end")
                 .text("M³/hr");

         svg.append("path")
                 .datum(dataset)
                 .attr("class", "line")
                 .attr("d", line);
    });

      //~~~ Format The Date:
      function formattedDateTime(dateAndTime) {
            var d = new Date(dateAndTime);
            var numDate = d.getDate();
            var numMonth = d.getMonth() + 1;
            var numYear = d.getFullYear();
            var numHours = d.getHours();
            var numMinutes = d.getMinutes();
            var numSeconds = d.getSeconds();
            numDate = (numDate < 10) ? "0" + numDate : numDate;
            numMonth = (numMonth < 10) ? "0" + numMonth : numMonth;
            numHours = (numHours < 10) ? "0" + numHours : numHours;
            numMinutes = (numMinutes < 10) ? "0" + numMinutes : numMinutes;
            numSeconds = (numSeconds < 10) ? "0" + numSeconds : numSeconds;

            return numYear + "/" + numMonth + "/" + numDate + " " + numHours + ":" + numMinutes + ":" + numSeconds;
      };
 Gerardo Furtado14 июл. 2016 г., 00:32
У вас есть эти ключи в вашем объекте? Еще лучше, вы можете вставить или сделать скриншот этого объекта?
 Gerardo Furtado14 июл. 2016 г., 01:00
Да,forEach будет повторятьмассив объектов.
 Gerardo Furtado14 июл. 2016 г., 01:10
Мне кажется, все в порядке. Я собирался сказать вам попробовать обозначение в скобках, но это не будет иметь никакого значения ... Теперь я думаю об асинхронности: вы уверены, что у вас загружен набор данныхдо для каждого?
 CaptEmulation14 июл. 2016 г., 00:55
Проблема в том, чтоdataset это объект, но вы пытаетесь использовать его как массив. Как упомянуто @ gerardo-furtado, нам нужно посмотреть, как выглядит этот объект, чтобы определить наилучший способ его итерации. Поскольку это объект, то с помощьюforEach не будет работать. Может бытьObject.keys(dataset).forEach или жеdataset.items.forEach верно...
 Mark14 июл. 2016 г., 16:10
Сделатьconsole.log(dataset) послеfor(i=0; i<itemCount; i++){ и обновите ваш вопрос с результатами. Похоже, вы строите массив строк в наборе данных, а не массив объектов. Ваш толчок должен выглядеть так:dataset.push({theTime: formattedDateTime(data.Items[i].Timestamp), theValue: data.Items[i].Value});, не уверен, почему ты строишь струны. Я думаю, что ваш набор данных действительно выглядитvar dataset = [ "{'theTime': '2016/07/12 15:58:40', 'theValue': 1123.07275390625}", ...]

Ответы на вопрос(2)

Cannot read property 'length' of undefined ошибка не исходит отdataset.forEachэто исходит откуда-то, где вы смотрите вверх.length чего-либо.

(Примечание: в инструментах разработчика Chrome вы можете просмотреть / развернуть ошибку в консоли и посмотреть, из какого файла и номера строки она произошла).

Если это происходит из какого-либо кода, которым вы поделились, то это оскорбительная строка:

var itemCount = data.Items.length;

Еслиdata.Items бывает неопределенным, вы получите эту ошибку. Так вставьтеconsole.log(data) на линии прямо перед строкой ошибок, проверьте вывод, ищитеdata.Items, чего скорее всего нет. Ваш диагноз должен указывать вам направление к его исправлению.

получите ли вы «массив объектов» или «объекты с ключом / значениями», я бы использовал _.forEach в библиотеке'Lodash' будет перебирать массив объектов ИЛИ ключ / значения объекта.

Ваш ответ на вопрос