You're viewing the legacy docs. They are deprecated as of May 18, 2016.
These docs are for version 2.4.2 and below of the Javascript SDK. Go to our current docs, or see our Web migration guide.

JavaScript Web Guide

Offline Capabilities

Firebase applications work even if your app loses its network connection temporarily. We provide several tools for monitoring presence and synchronizing local state with server state, which are introduced in this document.

Offline Behavior

Every client sharing a Firebase database maintains its own internal version of any active data. When data is updated or saved, it is written to this local version of the database. The Firebase client then synchronizes that data with the Firebase servers and with other clients on a 'best-effort' basis.

As a result, all writes to the database will trigger local events immediately, before any data has even been written to the server. This means the app will remain responsive regardless of network latency or Internet connectivity.

Once connectivity is reestablished, apps receive the appropriate set of events so that the client "catches up" with the current server state, without having to write any custom code.

Managing Presence

In realtime applications it is often useful to detect when clients connect and disconnect. For example, we may want to mark a user as 'offline' when their client disconnects.

Firebase clients provide simple primitives that allow data to be written to the database when a client disconnects from the Firebase servers. These updates will occur whether the client disconnects cleanly or not, so we can rely on them to clean up data even if a connection is dropped or a client crashes. All Firebase write operations, including setting, updating, and removing, can be performed upon a disconnection.

Here is a simple example of writing data upon disconnection by using the onDisconnect primitive:

var presenceRef = new Firebase('https://<YOUR-FIREBASE-APP>.firebaseio.com/disconnectmessage');
// Write a string when this client loses connection
presenceRef.onDisconnect().set("I disconnected!");

How onDisconnect Works

When an onDisconnect() operation is established, it lives on the Firebase server. The server checks security to make sure the user can perform the write event requested, and informs the client if it is invalid. The server then monitors the connection. If at any point it times out, or is actively closed by the client, the server checks security a second time (to make sure the operation is still valid) and then invokes the event.

The client can use the callback on the write operation to ensure the onDisconnect was correctly attached:

presenceRef.onDisconnect().remove( function(err) {
  if( err ) {
    console.error('could not establish onDisconnect event', err);
  }
});

An onDisconnect event can also be canceled by calling .cancel():

var onDisconnectRef = presenceRef.onDisconnect();
onDisconnectRef.set('I disconnected');
// some time later when we change our minds
onDisconnectRef.cancel();

Detecting Connection State

For many presence-related features, it is useful for a client to know when it is online or offline. Firebase clients provide a special location at /.info/connected which is updated every time the client's connection state changes. Here is an example:

var connectedRef = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/.info/connected");
connectedRef.on("value", function(snap) {
  if (snap.val() === true) {
    alert("connected");
  } else {
    alert("not connected");
  }
});

/.info/connected is a boolean values which is not synchronized between clients because the values are dependent on the state of the client. In other words, if one client reads /.info/connected as false, this is no guarantee that a separate client will also read false.

Handling Latency

Server Timestamps

Firebase servers provide a mechanism to insert timestamps generated on the server as data. This feature, combined with onDisconnect, provides an easy way to reliably make note of the time at which a client disconnected:

var userLastOnlineRef = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/users/joe/lastOnline");
userLastOnlineRef.onDisconnect().set(Firebase.ServerValue.TIMESTAMP);

Clock Skew

While Firebase.ServerValue.TIMESTAMP is much more accurate, and preferable for most read/write ops, it can occasionally be useful to estimate the clients clock skew with respect to Firebase's servers. We can attach a callback to the location /.info/serverTimeOffset to obtain the value, in milliseconds, that Firebase clients will add to the local reported time (epoch time in milliseconds) to estimate the server time. Note that this offset's accuracy can be affected by networking latency, and so is useful primarily for discovering large (> 1 second) discrepancies in clock time.

var offsetRef = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/.info/serverTimeOffset");
offsetRef.on("value", function(snap) {
  var offset = snap.val();
  var estimatedServerTimeMs = new Date().getTime() + offset;
});

Sample Presence App

By combining disconnect operations with connection state monitoring and server timestamps, we can build a user presence system. In this system, each user stores data at a database location to indicate whether or not a client is online. Clients set this location to true when they come online and a timestamp when they disconnect. This timestamp indicates the last time the given user was online.

Note that the disconnect operations should be queued before a user is marked online, to avoid any race conditions in case the client's network connection is lost before both commands can be sent to the server.

Here is a simple user presence system:

// since I can connect from multiple devices or browser tabs, we store each connection instance separately
// any time that connectionsRef's value is null (i.e. has no children) I am offline
var myConnectionsRef = new Firebase('https://<YOUR-FIREBASE-APP>.firebaseio.com/users/joe/connections');

// stores the timestamp of my last disconnect (the last time I was seen online)
var lastOnlineRef = new Firebase('https://<YOUR-FIREBASE-APP>.firebaseio.com/users/joe/lastOnline');

var connectedRef = new Firebase('https://<YOUR-FIREBASE-APP>.firebaseio.com/.info/connected');
connectedRef.on('value', function(snap) {
  if (snap.val() === true) {
    // We're connected (or reconnected)! Do anything here that should happen only if online (or on reconnect)

    // add this device to my connections list
    // this value could contain info about the device or a timestamp too
    var con = myConnectionsRef.push(true);

    // when I disconnect, remove this device
    con.onDisconnect().remove();

    // when I disconnect, update the last time I was seen online
    lastOnlineRef.onDisconnect().set(Firebase.ServerValue.TIMESTAMP);
  }
});
  1. 1

    Next

    Installation & Setup

  2. 2

    Next

    Understanding Data

  3. 3

    Next

    Saving Data

  4. 4

    Next

    Retrieving Data

  5. 5

    Next

    Structuring Data

  6. 6

    Next

    Understanding Security

  7. 7

    Next

    User Authentication

  8. 8

    Next

    Offline Capabilities

  9. 9

    Next

    Deploying Your App