I am using the following code to render an OHLC chart in CanvasJS:
<script>
var candleData = [];
var chart = new CanvasJS.Chart("chartContainer", {
title: {
text: 'Demo Stacker Candlestick Chart (Realtime)'
},
zoomEnabled: true,
axisY: {
includeZero: false,
title: 'Price',
prefix: '$'
},
axisX: {
interval: 1,
},
data: [{
type: 'ohlc',
dataPoints: candleData
}
]
});
function mapDataToPointObject(data) {
var dataPoints = [];
for(var i = 0; i < data.length; i++) {
var obj = data[i];
var newObj = {
x: new Date(obj.time),
y: [
obj.open,
obj.high,
obj.low,
obj.close
]
}
dataPoints.push(newObj);
}
return dataPoints;
}
function updateChart() {
$.ajax({
url: 'http://localhost:8080',
success: function(data) {
candleData = JSON.parse(data);
candleData = mapDataToPointObject(candleData);
chart.render();
}
});
}
$(function(){
setInterval(() => {
updateChart();
}, 500);
});
The data properly loads, parses into the correct format, and render()
is called on the interval like it should. The problem is, while the chart axes and titles all render properly, no data shows up. The chart is empty.
What DOES work is setting the data directly to the chart using
chart.options.data[0].dataPoints = candleData;
Why does my above solution not work then? Is there a way I can update the chart's dataPoints
without having to hardcode a direct accessor to the chart's dataPoints?
It's related to JavaScript pass by value and pass by reference.
After execution of the following line.
dataPoints: candleData
dataPoints will refer to the current value of candleData. ie. dataPoints = [];
Now if you redefine candleData to any other value.
candleData = JSON.parse(data);
candleData = mapDataToPointObject(candleData);
Then dataPoints won't be aware of this update and will still refer to the empty array (that you pointed earlier).
The following snippet will make it easy to understand
//pass by value
var a = "string1";
var b = a;
a = "string2";
alert("b is: " + b); //this will alert "string1"
//pass by reference
var c = { s: "string1" };
var d = c;
c.s = "string2";
alert("d.s is: " + d.s); //this will alert "string2"
For more, you can read about pass by value and pass by reference.