Quickstart: Use JavaScript to create an App showing GitHub star count with Azure Functions and SignalR Service

Azure SignalR Service lets you easily add real-time functionality to your application and Azure Functions is a serverless platform that lets you run your code without managing any infrastructure. In this quickstart, learn how to use SignalR Service and Azure Functions to build a serverless application with JavaScript to broadcast messages to clients.

Note

You can get all codes mentioned in the article from GitHub

Prerequisites

Note

This quickstart can be run on macOS, Windows, or Linux.

Having issues? Try the troubleshooting guide or let us know.

Log in to Azure

Sign in to the Azure portal at https://portal.azure.com/ with your Azure account.

Having issues? Try the troubleshooting guide or let us know.

Create an Azure SignalR Service instance

Your application will connect to a SignalR Service instance in Azure.

  1. Select the New button found on the upper left-hand corner of the Azure portal. In the New screen, type SignalR Service in the search box and press enter.

    Screenshot shows search for SignalR Service in the Azure portal.

  2. Select SignalR Service from the search results, then select Create.

  3. Enter the following settings.

    Setting Suggested value Description
    Resource name Globally unique name Name that identifies your new SignalR Service instance. Valid characters are a-z, 0-9, and -.
    Subscription Your subscription The subscription under which this new SignalR Service instance is created.
    Resource Group myResourceGroup Name for the new resource group in which to create your SignalR Service instance.
    Location West US Choose a region near you.
    Pricing tier Free Try Azure SignalR Service for free.
    Unit count Not applicable Unit count specifies how many connections your SignalR Service instance can accept. It is only configurable in the Standard tier.
    Service mode Serverless For use with Azure Functions or REST API.

    Screenshot shows SignalR Basics tab with values.

  4. Select Create to start deploying the SignalR Service instance.

  5. After the instance is deployed, open it in the portal and locate its Settings page. Change the Service Mode setting to Serverless only if you are using Azure SignalR Service through Azure Functions binding or REST API. Leave it in Classic or Default otherwise.

Having issues? Try the troubleshooting guide or let us know.

Setup and run the Azure Function locally

  1. Make sure you have Azure Function Core Tools installed. And create an empty directory and navigate to the directory with command line.

    # Initialize a function project
    func init --worker-runtime javascript
    
  2. After you initialize a project, you need to create functions. In this sample, we need to create 3 functions.

    1. Run the following command to create a index function, which will host a web page for client.

      func new -n index -t HttpTrigger
      

      Open index/function.json and copy the following json codes:

      {
        "bindings": [
          {
            "authLevel": "anonymous",
            "type": "httpTrigger",
            "direction": "in",
            "name": "req",
            "methods": [
              "get",
              "post"
            ]
          },
          {
            "type": "http",
            "direction": "out",
            "name": "res"
          }
        ]
      }
      

      Open index/index.js and copy the following codes.

      var fs = require('fs').promises
      
      module.exports = async function (context, req) {
          const path = context.executionContext.functionDirectory + '/../content/index.html'
          try {
              var data = await fs.readFile(path);
              context.res = {
                  headers: {
                      'Content-Type': 'text/html'
                  },
                  body: data
              }
              context.done()
          } catch (error) {
              context.log.error(err);
              context.done(err);
          }
      }
      
    2. Create a negotiate function for clients to get access token.

      func new -n negotiate -t SignalRNegotiateHTTPTrigger
      

      Open negotiate/function.json and copy the following json codes:

      {
        "disabled": false,
        "bindings": [
          {
            "authLevel": "anonymous",
            "type": "httpTrigger",
            "direction": "in",
            "methods": [
              "post"
            ],
            "name": "req",
            "route": "negotiate"
          },
          {
            "type": "http",
            "direction": "out",
            "name": "res"
          },
          {
            "type": "signalRConnectionInfo",
            "name": "connectionInfo",
            "hubName": "serverless",
            "connectionStringSetting": "AzureSignalRConnectionString",
            "direction": "in"
          }
        ]
      }
      
    3. Create a broadcast function to broadcast messages to all clients. In the sample, we use time trigger to broadcast messages periodically.

      func new -n broadcast -t TimerTrigger
      

      Open broadcast/function.json and copy the following codes.

      {
        "bindings": [
          {
            "name": "myTimer",
            "type": "timerTrigger",
            "direction": "in",
            "schedule": "*/5 * * * * *"
          },
          {
            "type": "signalR",
            "name": "signalRMessages",
            "hubName": "serverless",
            "connectionStringSetting": "AzureSignalRConnectionString",
            "direction": "out"
          }
        ]
      }
      

      Open broadcast/index.js and copy the following codes.

      var https = require('https');
      
      module.exports = function (context) {
          var req = https.request("https://api.github.com/repos/azure/azure-signalr", {
              method: 'GET',
              headers: {'User-Agent': 'serverless'}
          }, res => {
              var body = "";
      
              res.on('data', data => {
                  body += data;
              });
              res.on("end", () => {
                  var jbody = JSON.parse(body);
                  context.bindings.signalRMessages = [{
                      "target": "newMessage",
                      "arguments": [ `Current star count of https://github.com/Azure/azure-signalr is: ${jbody['stargazers_count']}` ]
                  }]
                  context.done();
              });
          }).on("error", (error) => {
              context.log(error);
              context.res = {
                status: 500,
                body: error
              };
              context.done();
          });
          req.end();
      }    
      
  3. The client interface of this sample is a web page. Considered we read HTML content from content/index.html in index function, create a new file index.html in content directory under your project root folder. And copy the following content.

    <html>
    
    <body>
      <h1>Azure SignalR Serverless Sample</h1>
      <div id="messages"></div>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/3.1.7/signalr.min.js"></script>
      <script>
        let messages = document.querySelector('#messages');
        const apiBaseUrl = window.location.origin;
        const connection = new signalR.HubConnectionBuilder()
            .withUrl(apiBaseUrl + '/api')
            .configureLogging(signalR.LogLevel.Information)
            .build();
          connection.on('newMessage', (message) => {
            document.getElementById("messages").innerHTML = message;
          });
    
          connection.start()
            .catch(console.error);
      </script>
    </body>
    
    </html>
    
  4. It's almost done now. The last step is to set a connection string of the SignalR Service to Azure Function settings.

    1. In the browser where the Azure portal is opened, confirm the SignalR Service instance you deployed earlier was successfully created by searching for its name in the search box at the top of the portal. Select the instance to open it.

      Search for the SignalR Service instance

    2. Select Keys to view the connection strings for the SignalR Service instance.

      Screenshot that highlights the primary connection string.

    3. Copy the primary connection string. And execute the command below.

      func settings add AzureSignalRConnectionString "<signalr-connection-string>"
      
  5. Run the Azure Function in local:

    func start
    

    After Azure Function running locally. Use your browser to visit http://localhost:7071/api/index and you can see the current star count. And if you star or unstar in the GitHub, you will get a star count refreshing every few seconds.

    Note

    SignalR binding needs Azure Storage, but you can use local storage emulator when the Function is running locally. If you got some error like There was an error performing a read operation on the Blob Storage Secret Repository. Please ensure the 'AzureWebJobsStorage' connection string is valid. You need to download and enable Storage Emulator

Having issues? Try the troubleshooting guide or let us know

Clean up resources

If you're not going to continue to use this app, delete all resources created by this quickstart with the following steps so you don't incur any charges:

  1. In the Azure portal, select Resource groups on the far left, and then select the resource group you created. Alternatively, you may use the search box to find the resource group by its name.

  2. In the window that opens, select the resource group, and then click Delete resource group.

  3. In the new window, type the name of the resource group to delete, and then click Delete.

Having issues? Try the troubleshooting guide or let us know.

Next steps

In this quickstart, you built and ran a real-time serverless application in local. Learn more how to use SignalR Service bindings for Azure Functions. Next, learn more about how to bi-directional communicating between clients and Azure Function with SignalR Service.