CHAPTER 14
Let us have a look at some other fun things to do with SignalR. Let’s get an exchange rate chart going. We can leave all the code as is. We are just going to modify our charting.js file.
First, we need to find a place from which to grab some real-time exchange rates. For this purpose, Alpha Vantage has a very nice API; to use it, we will need to get a free API key. You can do so by clicking on this link.
Note: Because this is a free API, I will not make more than 5 API requests per minute.
Head on over to their detailed documentation page and see some of the endpoints that they provide. For this demo, I’ll just be using the foreign exchange rate of US dollars (USD) to South African rand (ZAR).
Note: Be sure to add your API key to the end of the URL, after the apikey= parameter.
For this demo, the endpoint URL looks as follows.
Having a look at the JSON returned from the API call, I can see that the exchange rate is looking rather bad (Code Listing 37).
Code Listing 37
{ "Realtime Currency Exchange Rate": { "1. From_Currency Code": "USD", "2. From_Currency Name": "United States Dollar", "3. To_Currency Code": "ZAR", "4. To_Currency Name": "South African Rand", "5. Exchange Rate": "19.03840000", "6. Last Refreshed": "2020-04-26 22:02:52", "7. Time Zone": "UTC", "8. Bid Price": "19.03660000", "9. Ask Price": "19.04660000" } } |
We have a bid price of 19.0366 and an asking price of 19.0466. Modify the code in your charting.js file as follows.
Start by adding a timer on an interval of 15 seconds (15,000 milliseconds) that calls a function called fireApi, as seen in Code Listing 38.
Code Listing 38
window.setInterval(fireApi, 15000); |
Next, we need to edit our lineChart object. We will define the chart as having a low of 19.0 and a high of 19.06. This is based off of the bid price and asking price as seen in the JSON returned from the API call (Code Listing 37).
Code Listing 39
var lineChart = new Chartist.Line('#chartArea', { labels: [], series: [[]] }, { low: 19.0, high: 19.06, showArea: true }); |
I also want to display the exchange rate somewhere, so I’m just going to repurpose the valueInput text box for this. Therefore, I need to remove the clearing out of the value and setting the focus after the chart is updated. The commented-out code can be seen in Code Listing 40.
Code Listing 40
connection.on("ValueReceiver", function (chartValue) { if (chartValue && !isNaN(chartValue)) { lineChart.data.series[0].push(chartValue); lineChart.update(); //document.getElementById("valueInput").value = ""; //document.getElementById("valueInput").focus(); } }); |
We now need to write an API call in the fireApi function being called by the timer. Create a function called fireApi and add the code seen in Code Listing 41. This will call the API, inspect the result, and extract the exchange rate from the JSON.
The exchange rate is parsed as a float and passed to the ValueSender method in the hub. The valueInput text box is then set to the value of the current exchange rate read from the returned JSON.
Code Listing 41
function fireApi() { $.ajax({ type: "GET", url: "https://www.alphavantage.co/query?function=CURRENCY_EXCHANGE_RATE&from_currency=USD&to_currency=ZAR&apikey=UKHCKPYSU94IQMAQ", dataType: "json", success: function (result, status, xhr) { var exchRate = result["Realtime Currency Exchange Rate"]["5. Exchange Rate"]; if (exchRate) { var chartValue = parseFloat(exchRate); connection.invoke("ValueSender", chartValue).catch(function (err) { return console.error(err.toString()); }); } document.getElementById("valueInput").value = exchRate; }, error: function (xhr, status, error) { alert("Result: " + status + " " + error + " " + xhr.status + " " + xhr.statusText) } }); } |
You can see the complete code listing for the modified charting.js file in Code Listing 42.
Code Listing 42
"use strict"; window.setInterval(fireApi, 15000); var lineChart = new Chartist.Line('#chartArea', { labels: [], series: [[]] }, { low: 19.0, high: 19.06, showArea: true }); var connection = new signalR.HubConnectionBuilder().withUrl("/chartHub").build(); //Disable send button until connection is established. document.getElementById("sendButton").disabled = true; connection.on("ValueReceiver", function (chartValue) { if (chartValue && !isNaN(chartValue)) { lineChart.data.series[0].push(chartValue); lineChart.update(); //document.getElementById("valueInput").value = ""; //document.getElementById("valueInput").focus(); } }); connection.start().then(function () { document.getElementById("sendButton").disabled = false; }).catch(function (err) { return console.error(err.toString()); }); document.getElementById("sendButton").addEventListener("click", function (event) { var strValue = document.getElementById("valueInput").value; var chartValue = parseFloat(strValue); connection.invoke("ValueSender", chartValue).catch(function (err) { return console.error(err.toString()); }); event.preventDefault(); }); $('#valueInput').keypress(function (e) { var key = e.which; if (key === 13) // the enter key code. { $('#sendButton').click(); return false; } }); function fireApi() { $.ajax({ type: "GET", url: "https://www.alphavantage.co/query?function=CURRENCY_EXCHANGE_RATE&from_currency=USD&to_currency=ZAR&apikey=UKHCKPYSU94IQMAQ", dataType: "json", success: function (result, status, xhr) { var exchRate = result["Realtime Currency Exchange Rate"]["5. Exchange Rate"]; if (exchRate) { var chartValue = parseFloat(exchRate); connection.invoke("ValueSender", chartValue).catch(function (err) { return console.error(err.toString()); }); } document.getElementById("valueInput").value = exchRate; }, error: function (xhr, status, error) { alert("Result: " + status + " " + error + " " + xhr.status + " " + xhr.statusText) } }); } |
Go ahead and run your application, and leave it running for a couple of minutes. Watch as the API is called every 15 seconds, and the exchange rate value is updated in the Value text box on the page.
As the value changes after each API call, the line chart is also updated at the same time. After a few minutes, you should end up with a line chart resembling the chart in Figure 41.

Figure 41: Exchange Rate Chart
Play around some more with other API endpoints you might know of. The data can sometimes surprise you once it’s charted in a nice line or bar chart.