如何阻止我的javascript锁定浏览器?

时间:2017-11-10 11:01:33

标签: javascript websocket

我有WebSocket以~50hz的速率接收数据。每次将更新推送到浏览器时,它都会将已发布的JSON数据转换为一些漂亮的图表。

$(document).ready(function() {
    console.log('Connecting web socket for status publishing')
    allRawDataPublisher = new ReconnectingWebSocket("ws://" + location.host + '/raw/allrawdata');

    var rawUnprocessedData = [];

    for (i = 0; i < 256; i++)
    {
        rawUnprocessedData.push({x:i, y:0});
    }

    var unprocessedRawChart = new CanvasJS.Chart("rawUnprocessedData",{
        title :{ text: "Raw Unprocessed Data"},
        axisX: { title: "Bin"},
        axisY: { title: "SNR"},
        data: [{ type: "line", dataPoints : rawUnprocessedData},{ type: "line", dataPoints : noiseFloorData}]
    });

    var updateChart = function (dps, newData, chart) {
        for (i = 0; i < 256; i++)
        {
          dps[i].y = newData[i];
        }
        chart.render();
    };

    allRawDataPublisher.onmessage = function (message) {
        jsonPayload = JSON.parse(message.data);
        var dataElements = jsonPayload["Raw Data Packet"]
        updateChart(rawUnprocessedData, dataElements["RAW_DATA"].Val, unprocessedRawChart)
    };

    unprocessedRawChart.render();
});

当我的笔记本电脑插入电源插座时,这种方法很有效但是如果我拔掉电源,我的笔记本电脑就会降低它的处理能力(同样的问题出现在规格较低的平板电脑,手机等)。当可用的处理能力较低时,浏览器(Chrome)会完全锁定。

我猜测javascript接收更新的速度比浏览器可以渲染它们更快,从而锁定了标签。

如果浏览器无法以请求的速率更新,我希望它能够删除新数据,直到它准备好呈现新的更新。有没有一种标准的方法来检查浏览器是否有足够的时间来呈现更新并删除新的帧(如果不是这样的话)?

* [编辑]

我使用Chrome的分析器进行了一些挖掘,这证实了(正如预期的那样)它正在重新绘制占据大部分处理能力的图表。

1 个答案:

答案 0 :(得分:2)

您可以使用window.requestAnimationFrame在框架之间进行工作。

传递给此函数的回调最多每秒调用60次 - 或者与显示器的刷新率匹配的任何一个。

还保证在下一次重绘之前调用 - 并且之前的重绘完成之后

来自MDN window.requestAnimationFrame()

  

window.requestAnimationFrame()方法告诉浏览器您希望执行动画并请求浏览器调用指定的函数以在下次重绘之前更新动画。该方法将回调作为在重绘之前调用的参数。

以下是如何使用它的示例:

function renderChart () {
   // pull data from your array and do rendering here
   console.log('rendering...')
   requestAnimationFrame(renderChart)
}

requestAnimationFrame(renderChart)

但是,最好在批次中对图表进行更改,而不是为每个帧中的每个数据进行渲染工作。

以下是使用Fiddle代码的Chart.js代码:

  • 每100毫秒(10赫兹)将数据推送到Array
  • 以每1000毫秒(1赫兹)的速度分组渲染数据
const values = []
const ctx = document.getElementById('chartContainer').getContext('2d');
const chart = new Chart(ctx, {
  type: 'line',
  data: {
    labels: ['start'],
    datasets: [{
      label: 'mm of rain',
      data: [1],
      borderWidth: 1
    }]
  }
});

// Push 1 item every 100ms (10 Hz), simulates 
// your data coming through at a faster
// rate than you can render
setInterval(() => {
  values.push(Math.random())
}, 100)

// Pull last 4 items every 1 second (1 Hz)
setInterval(() => {
  // splice last 4 items, add them to the chart's data
  values.splice(values.length - 4, 4)
    .forEach((value, index) => {
      chart.data.labels.push(index)
      chart.data.datasets[0].data.push(value)
    })

  // finally, command the chart to update once!
  chart.update()
}, 1000)

请注意,上述概念需要适当地处理异常,否则values Array将开始累积过程耗尽内存的数据。

您还必须小心渲染批次的方式。如果您的值渲染率低于填充values Array的速率,则最终会遇到内存问题。

最后但同样重要的是:我不相信你需要更快地更新2 Hz的数据,因为我怀疑人类大脑能够以如此快的速度做出有用的解释。