Table of Contents

Introduction

This lesson is about using Firebase's Realtime Database for communication between web applications. The Realtime Database uses Websockets for communication between clients and server.

Create Firebase account and project

The first thing we need is to get an account in Firebase and create a project.

Head on to https://firebase.google.com/, create an account and sign-in.

After you sign-in, head over to the Console (Figure 1).

Figure 1.

In the Console, hit the "Create New Project" button and enter the name for your project. After the project is created you should see something like Figure 2.

Figure 2.

In Figure 2, note the "Add Firebase to your web app" button - if you click there you will see the necessary JavaScript code to include Firebase in your app. Also note on the left pane, the "Database" section - that's the Realtime Database we will be using.

Setting up anonymous sign-in method

We will want our users to be able to sign-in anonymously (you could use a proper register/sign-in process, but for simplicity let's go with anonymous). For this we need to enable anonymous authentication in Firebase. Follow the screenshots:

Figure 3. Go to authentication pane.
Figure 4. Select anonymous authentication.
Figure 5. Enable anonymous authentication.

Using Firebase in our web application

The first thing is to include the necessary code you obtain from the previous step. Click on the "Add Firebase to your web app" and copy the code to your project. (The code in the second <script> tag should go to an external JavaScript file as we have done previously.

In these examples, we will not require users to register and log in. Instead, we are going to let users log in anonymously. To make things easier, I created a simple example that:

  • Configures the Firebase app (replace the info with your own)
  • Signs the user anonymously
  • Calls the init() function

In the init() function we can put all our JavaScript code and be sure that we can use all Firebase functions:

  // Initialize Firebase
// Copy the config from your own Firebase app 
var config = {
    apiKey: "[your api key]",
    authDomain: "[your auth domain]",
    databaseURL: "[your database url]",
    storageBucket: "[your storage bucket]",
    messagingSenderId: "[your messaging sender id]"
};
app = firebase.initializeApp(config);

var inited = false;
var user;
app.auth().onAuthStateChanged(function(user) {
    if (user) {
        // User is signed in.
        window.user = user;
        console.log("User:", user.uid);
        if (!inited) {
            inited = true;
            init();
        }
    } else {
        app.auth().signInAnonymously().catch(function(error) {
            console.log(error);
        });
    }
});
/// Copy until this line 

// You should have an init function as the main entry point
function init() {
    var db = app.database();

}

Write data to the database

To write data in the database we just call db.ref([key]).set([value]);. Firebase's Realtime Database is based on the JavaScript object structure, so to write we need to know to which key we want to associate the value.

If you run the following code inside your init() function

  var db = app.database();
db.ref("myname").set("jorge cardoso");

You can see that the value has been written by using the Firebase's Database dashboard (Figure 6).

Figure 6. Database dashboard.

The values we write can be JavaScript objects:

  db.ref("user").set({username: "jorge", email:"jorgecardoso@ieee.org"});

Figure 7. Writing a JavaScript object.

We can also write add values to a location, creating a collection of items:

  db.ref("messages").push({message:"Hi, how are you?", date:"10/04/2017", to:"jorge"});
var pushedReference = db.ref("messages").push({message:"Fine!", date:"10/04/2017", to:"someuser"});

Figure 8. Pushing items to a location.

We we use the push() function, Firebase will automatically assign a unique id as the key of the value we are pushing. The push() function will return a reference to the created value so we can manipulate it further:

  pushedReference.set({message:"Fine!", date:"10/04/2017", to:"me"});

We can create/update/change values at any depth in the database. For example to change the username of the user we created before, we could:

  db.ref("user").child("username").set("jorgecardoso"); // or
db.ref("user/username").set("jorge_cardoso")

Notice that in all these examples, we did not need to create any pre-defined structure in the database. It will automatically create, delete, and update values and keys.

To delete a value, we can just set it to null or call the remove() function:

  db.ref("myname").set(null); //or
//db.ref("myname").remove();

Listen for data changes

Clients can listen to data changes in the database to be informed of any update by any other client (or itself).

To listen to value changes on a specific location of the database we use the on() function and the value event:

  db.ref("myname").on("value", function(snapshot) {
    console.log("myname changed: ", snapshot.val());
});

To test this code you should define the value listener before the code that writes to the database, e.g.:

  var db = app.database();

db.ref("myname").on("value", function(snapshot) {
    console.log("myname changed: ", snapshot.val());
});

db.ref("myname").set("jorge cardoso");

Notice that your own writes trigger the value change event.

Collections

We can also listen to events related to collections, e.g., when an item is added, (or removed, or updated) to a collection. For that, we use the child_added event on the location of the collection:

  db.ref("messages").on("child_added", function(snapshot) {
    console.log(snapshot.val());
});

If you run your code multiple times, you will notice that the on("child_added") is called multiple times. That is because the event is triggered for all existing elements in the collection. We can limit the number of children to be synced using the limitToLast(n) function:

  db.ref("messages").limitToLast(2).on("child_added", function(snapshot) {
    console.log(snapshot.val());
});

This will only trigger two events at startup, and then will trigger for every new added child.

OnDisconnect

A frequent use case is informing the server and other connected clients, when a given client disconnects (by closing the browser window, losing network connectivity, or explicit user disconnection). Firebase offers a specific function for this, the onDisconnect:

  // inform about us
var userRef = db.ref("currentUsers").push({username:"jorge"});
userRef.onDisconnect().remove();

$("button").on("click", function() {
    userRef.remove();
});

In this example, we first inform other clients of our presence. We then intruct Firebase to automatically remove the pushed data if we disconnect. We also give the user the possibility of mannually disconnecting (not really disconnecting but removing itself from the list of current users).