Real-time Chart in JavaScript with ChartJS and Hamoni Sync

综合技术 2018-05-18 阅读原文

Real-time Chart in JavaScript with ChartJS and Hamoni Sync

Photo by on

Real-time data is data that is presented as it is acquired. It is often used in tracking or monitoring systems like traffic GPS system, auction/bidding applications and stock trading applications. Charts help with a graphical representation of this data and help the viewer make a decision easily.

In this post, I’ll show you how to make real-time chart in JavaScript. We’ll be building a basic voting web application with a page for voting, and another page with a real-time chart showing the voting result as it happens. Here’s a peek at what we’ll be building

I’ll be using Chart.js and Hamoni Sync to build it. Chart.js is a simple JavaScript charting library. Hamoni Sync is a real-time state synchronisation service which enables you to synchronise your application state in real-time. The vote result is the state we want show users in real-time. Hamoni Sync makes this easier by allowing you to define state for your application, while you avoid designing complex state logic around publish/subscribe systems.

Setup the code

We will be using a project template which already has the HTML pages and node app to serve the static files. Follow the instruction below to set it up

  1. Clone the repo from GitHub by running git clone in the command line. If you’re not using git, you can download it here .
  2. Switch to the project directory cd realtime-chartjs-hamoni-starter
  3. Install the dependencies by running npm install . This will install express and Hamoni Sync node modules. # Backend

The server.js file contains code to server HTML pages in the public folder. Lines 9–14 defines a default state for the voting application. It contains 4 candidates with their vote count as 0.

let voteData = [
      { candidate: "Peter Mbanugo", vote: 0 },
      { candidate: "Angela Daniels", vote: 0 },
      { candidate: "Rose Philly", vote: 0 },
      { candidate: "James Crump", vote: 0 }

It also defines a REST endpoint for voting defined from lines 18 to 30. When a vote comes in, we may want to save that data to a database and then update the chart with an up-to-date result of the vote. The chart state will be communicated in real-time using Hamoni Sync. On line 40 I have declared a statement to initialise Hamoni but we need an account ID and app ID.

Create Hamoni Account and App

Login to the Hamoni dashboard (or Signup if you don’t already have an account). When logged in you can click the Show Account ID button to see your account ID. We need a Hamoni App ID, hence we need to create an app from the dashboard. An app is a container that can hold application state. You’d typically want to have a separate Hamoni app for each of your application.

Under the “Create Application” header, enter an application name and click the create button. Within a few seconds, you should see it created and displayed in the application list section.

Copy the app and account ID and replace them with the string value on line 40 in server.js

Create application state in Hamoni

Now we need to create state in Hamoni Sync. To do that we need to use a sync primitive. Sync primitives are what you use to define and manipulate state. They’re basically a way to categorise or differentiate kinds of data to be stored. There are 3 sync primitives:

  1. Value Primitive: This kind of state holds simple information represented with datatypes like string, boolean or numbers. It is best suited for cases such as unread message count, toggles, etc.
  2. Object Primitive: Object state represents states that can be modelled as a JavaScript object. An example usage could be storing the score of a game.
  3. List Primitive: This holds a list of state objects. A state object is a JavaScript object. You can update an item based on its index in the list.

I’ll be using an object primitive for this post.

Add the following function in server.js

function createState() {
        .createObject("election", voteData)
        .then(statePrimitive => {
          console.log("election state created");
          state = statePrimitive;

This creates a state with the name of *election* * and state value using the variable `*voteData *.* Then we need to connect to the Hamoni Sync server. We do this by calling hamoni.connect() . Add the following code below the function createState()`

hamoni.connect().then(() => createState()).catch(console.log);

If it connects successfully to the server, we call the createState() function to create the state for our chart.

Update application state

We want to update the state when a new vote comes in. The object primitive which holds our state has an update() method which can be used to update the state. We will update the election state when the user calls /vote endpoint of our API. Below lines 27, add the following code to update the state"/vote", function(req, res) {

This will update the state and broadcast the update to connected clients.


Our backend is ready to accept votes and update the state. Now we need to build the frontend to send in votes and display realtime chart.

The starter template we cloned at the beginning has the files public/vote.html and public/js/vote.js. These files already contain code to display a form in the web page and javascript to post to the server. I skipped writing that code here because it’s a basic HTML form and JavaScript to send form data to the server. Do leave a comment if anything there is confusing.

The chart will be displayed in index.html inside the public folder. index.html already contains script tags for Chart.js and Hamoni Sync (see lines 17 and 18)


Render the chart

Open the file public/index.js. Add the function below to render a chart in the web page.

function renderChart(state) {
      var ctx = document.getElementById("myChart").getContext("2d");
      var chart = new Chart(ctx, {
        // The type of chart we want to create
        type: "bar",
        // The data for our dataset
        data: {
          labels: => s.candidate),
          datasets: [
              label: "Elections 2018",
              backgroundColor: "rgb(255, 99, 132)",
              borderColor: "rgb(255, 99, 132)",
              data: =>
        // Configuration options go here
        options: {
          scales: {
            xAxes: [
                time: {
                  unit: "Vote"
                gridLines: {
                  display: false
                ticks: {
                  maxTicksLimit: 6
            yAxes: [
                ticks: {
                  min: 0,
                  max: 30,
                  maxTicksLimit: 10
                gridLines: {
                  display: true
          legend: {
            display: true

This function takes a parameter that represents our chart state. The type options specify the type of chart we want to render, in this case, a bar chart. The data option defines properties used to display data for the chart. There are two important properties that I want to bring to your attention. First is the label property on line 8, labels:*s*

*=>*` `s.candidate)`
It gets its value from the state. The chart state is an array of each electoral candidate and their vote. With that code, we’re setting the candidate’s name as labels for the chart. The second is `data:``*s*`

=>` on line 14. It sets the data for the chart.

Now we need to retrieve chart state and render the chart.

Get state and state updates

To retrieve the chart state, we need to connect to Hamoni Sync. Add the following code to get state and state updates, then render the chart based on that:

let hamoni = new Hamoni("Account_ID", "APP_ID");
  .then(response => {
      .then(statePrimitive => {
statePrimitive.onUpdated(state => renderChart(state));
  .catch(error => console.log(error));

If the client successfully connects to Hamoni Sync, we call hamoni.get("election") to get our election state. If it succeeds, we call renderCharts() with the value for the state.

To be notified of state updates, we call onUpdated() on the state primitive with a callback that should be executed each time there’s an update.

Now we can test our code to see it working. Open the command line and run npm start , then open your browser and navigate to localhost:5000 .

Voila!! :rocket:

Real-time chart state made with less hassle. Chart.js is easy to use. Hamoni Sync reduces the development time and effort in designing complex state logic around publish/subscribe systems because it embraces the concept of state.

You can get the finished source code on GitHub .


Also shared on

Hacker Noon

责编内容by:Hacker Noon阅读原文】。感谢您的支持!


Book Review : JavaScript: The Good Parts I have to be be honest, in all my time as a software developer there are very few development tutorial textbooks which I would recommend. I have purch...
原生js的常用方法 前言:随着前端市场日新月异的发展,现如今的市场要的不只是会切切图的小仔、小妹了,而是需要真正懂原生js闭包,继承,原型链,node,以及熟读源码的大神,那么我们也不能太落后各位大神,撸起袖子,重新拾起原生js吧! 以下是个人总结,也有一些是copy大神的,现在放到一起,方便以后查阅(有不对的地方...
Adventures in Microbenchmarking When we’re trying to speed up some part of our code, we want quick, targeted feedback about how our changes perform against the initial implementatio...
Why does this give me an error? Why is this code giving me the following error message? TypeError: Object 97 has no method 'charCodeAt'var str = "Caesar Cipher"; str = str.spli...
JS中与正则有关的方法 最近正在拜读老姚的 《JavaScript 正则表达式迷你书》 ,碰巧项目中也会时不时的用到正则,所以今天来总结一下JS中有关正则的方法。 RegExp对象方法 test() 字符串的 test() 方法,比较常用在判断语句中,最简单的RegExp方法...