进行实时数据表更新

时间:2015-05-12 21:19:29

标签: node.js socket.io socket.io-redis

我构建了一个应用程序,它通过socketio消耗来自redis频道(卖家)的数据,并将数据实时推送到前端。数据集最多可包含一千行,因此我正在考虑使用数据表以干净的方式表示数据。表元素将定期更新,但不会添加/删除行,只会更新。

我面临的问题是,由于我对可视化生态系统缺乏经验,我不知道哪种方法可以实现。我一直在玩弄d3js,但我认为很难快速准备一些东西并且尝试使用datatables js库但是我没有看到如何使数据表实时化。< / p>

这是前端的代码摘录:

socket.on('sellers', function(msg){
  var seller = $.parseJSON(msg);
  var sales = [];
  var visits = [];
  var conversion = [];
  var items = seller['items'];

  var data = [];
  for(item in items) {
    var item_data = items[item];
    //data.push(item_data)
    data.push([item_data['title'], item_data['today_visits'], item_data['sold_today'], item_data['conversion-rate']]);
  }

  //oTable.dataTable(data);

  $(".chart").html("");
  drawBar(data);
});

1 个答案:

答案 0 :(得分:1)

使用d3解决您的问题简单而优雅。今天早上我花了一点时间来创造一个你可以适应自己需要的小提琴:

http://jsfiddle.net/CelloG/47nxxhfu/

要使用d3,您需要了解将数据连接到html元素的工作原理。请查看http://bost.ocks.org/mike/join/以获取作者的简要说明。

小提琴中的代码是:

var table = d3.select('#data')

// set up the table header
table.append('thead')
    .append('tr')
    .selectAll('th')
        .data(['Title', 'Visits', 'Sold', 'Conversion Rate'])
    .enter()
        .append('th')
        .text(function (d) { return d })

table.append('tbody')

// set up the data
// note that both the creation of the table AND the update is
// handled by the same code.  The code must be run on each time
// the data is changed.

function setupData(data) {
    // first, select the table and join the data to its rows
    // just in case we have unsorted data, use the item's title
    // as a key for mapping data on update
    var rows = d3.select('tbody')
        .selectAll('tr')
        .data(data, function(d) { return d.title })

    // if you do end up having variable-length data,
    // uncomment this line to remove the old ones.
    // rows.exit().remove()

    // For new data, we create rows of <tr> containing
    // a <td> for each item.
    // d3.map().values() converts an object into an array of
    // its values
    var entertd = rows.enter()
        .append('tr')
            .selectAll('td')
                .data(function(d) { return d3.map(d).values() })
            .enter()
                .append('td')

    entertd.append('div')
    entertd.append('span')

    // now that all the placeholder tr/td have been created
    // and mapped to their data, we populate the <td> with the data.

    // First, we split off the individual data for each td.
    // d3.map().entries() returns each key: value as an object
    // { key: "key", value: value}
    // to get a different color for each column, we set a
    // class using the attr() function.

    // then, we add a div with a fixed height and width
    // proportional to the relative size of the value compared
    // to all values in the input set.
    // This is accomplished with a linear scale (d3.scale.linear)
    // that maps the extremes of values to the width of the td,
    // which is 100px

    // finally, we display the value.  For the title entry, the div
    // is 0px wide
    var td = rows.selectAll('td')
        .data(function(d) { return d3.map(d).entries() })
        .attr('class', function (d) { return d.key })

    // the simple addition of the transition() makes the
    // bars update smoothly when the data changes
    td.select('div')
        .transition()
        .duration(800)
        .style('width', function(d) {
            switch (d.key) {
                case 'conversion_rate' :
                    // percentage scale is static
                    scale = d3.scale.linear()
                        .domain([0, 1])
                        .range([0, 100])
                    break;
                case 'today_visits': 
                case 'sold_today' :
                    scale = d3.scale.linear()
                    .domain(d3.extent(data, function(d1) { return d1[d.key] }))
                    .range([0, 100])
                    break;
                default:
                    return '0px'
            }
            return scale(d.value) + 'px'
        })
    td.select('span')
        .text(function(d) {
            if (d.key == 'conversion_rate') {
                return Math.round(100*d.value) + '%'
            }
            return d.value
        })
}

setupData(randomizeData())

d3.select('#update')
    .on('click', function() {
        setupData(randomizeData())
    })

// dummy randomized data: use this function for the socketio data
// instead
//
// socket.on('sellers', function(msg){
//  setupData(JSON.parse(msg).items)
// })
function randomizeData() {
    var ret = []
    for (var i = 0; i < 1000; i++) {
        ret.push({
            title: "Item " + i,
            today_visits: Math.round(Math.random() * 300),
            sold_today: Math.round(Math.random() * 200),
            conversion_rate: Math.random()
        })
    }
    return ret
}