Teste o Cloud Firestore: conheça o banco de dados escalonável e flexível do Firebase e do Google Cloud Platform. Saiba mais sobre o Cloud Firestore.

Como ativar recursos off-line no JavaScript

Os aplicativos do Firebase funcionam mesmo se o app perder temporariamente a conexão com a rede. Fornecemos várias ferramentas para monitorar a presença e sincronizar o estado local com o estado do servidor. Essas ferramentas serão apresentadas neste documento.

Como gerenciar a presença

Nos apps em tempo real, costuma ser útil detectar quando os clientes se conectam e desconectam. Por exemplo, para marcar um usuário como off-line quando o cliente dele se desconecta.

Os clientes do Firebase Database oferecem primitivos simples que você pode usar para gravar no banco de dados quando um cliente se desconecta dos servidores do Firebase Database. Podemos confiar nessas atualizações para limpar os dados quando uma conexão é perdida ou quando ocorre uma falha no cliente porque elas são executadas mesmo quando o cliente se desconecta incorretamente. Todas as operações de gravação, como configuração, atualização e remoção, podem ser executadas após uma desconexão.

Este é um exemplo simples de gravação de dados após a desconexão usando o primitivo onDisconnect:

var presenceRef = firebase.database().ref("disconnectmessage");
// Write a string when this client loses connection
presenceRef.onDisconnect().set("I disconnected!");

Como o onDisconnect funciona

Quando você estabelece uma operação onDisconnect(), ela reside no servidor do Firebase Realtime Database. O servidor verifica a segurança para garantir que o usuário possa executar o evento de gravação solicitado e informa ao app se ele for inválido. Em seguida, o servidor monitora a conexão. Se, a qualquer momento, o tempo limite da conexão se esgotar ou se ela for ativamente fechada pelo cliente do Realtime Database, o servidor verificará a segurança mais uma vez para garantir que a operação ainda seja válida e depois invocará o evento.

O app pode usar o retorno de chamada na operação de gravação para garantir que o onDisconnect foi corretamente anexado:

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

Também é possível cancelar um evento onDisconnect chamando .cancel():

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

Como detectar o estado da conexão

Para muitos recursos relacionados à presença, é útil que o app saiba quando está on-line ou off-line. O Firebase Realtime Database dispõe de um local especial em /.info/connected, que é atualizado sempre que o estado da conexão do cliente do Firebase Realtime Database muda. Veja um exemplo:

var connectedRef = firebase.database().ref(".info/connected");
connectedRef.on("value", function(snap) {
  if (snap.val() === true) {
    alert("connected");
  } else {
    alert("not connected");
  }
});

/.info/connected é um valor booleano não sincronizado entre os clientes do Realtime Database, porque esse valor depende do estado deles. Em outras palavras, se um cliente lê /.info/connected como "false" (falso), isso não garante que outro cliente também faça a mesma leitura.

Como gerenciar a latência

Timestamps do servidor

Os servidores do Firebase Realtime Database têm um mecanismo para inserir carimbos de data/hora gerados no servidor como dados. Combinado com o onDisconnect, esse recurso é uma maneira fácil de registrar o horário em que um cliente do Realtime Database se desconectou:

var userLastOnlineRef = firebase.database().ref("users/joe/lastOnline");
userLastOnlineRef.onDisconnect().set(firebase.database.ServerValue.TIMESTAMP);

Defasagem horária

O firebase.database.ServerValue.TIMESTAMP é muito mais preciso e indicado para a maioria das operações de leitura/gravação, mas em algumas situações é importante estimar a defasagem horária dos clientes em relação aos servidores do Firebase Realtime Database. Anexe um retorno de chamada ao local /.info/serverTimeOffset para receber o valor, em milissegundos, que os clientes do Firebase Realtime Database adicionam ao horário local informado (tempo de época em milissegundos) para estimar o horário do servidor. A precisão dessa diferença pode ser afetada pela latência da rede e, portanto, é útil principalmente para descobrir as grandes discrepâncias de mais de um segundo no horário do relógio.

var offsetRef = firebase.database().ref(".info/serverTimeOffset");
offsetRef.on("value", function(snap) {
  var offset = snap.val();
  var estimatedServerTimeMs = new Date().getTime() + offset;
});

Exemplo de app de presença

Combine as operações de desconexão com o monitoramento de estado da conexão e os carimbos de data/hora do servidor para criar um sistema de presença do usuário. Nesse sistema, cada usuário armazena dados em um local do banco de dados para indicar se um cliente do Realtime Database está on-line. Os clientes definem esse local como verdadeiro quando ficam on-line e um carimbo de data/hora quando se desconectam. Esse carimbo de data/hora indica a última vez em que o usuário esteve on-line.

Observe que o app precisa colocar as operações de desconexão em fila antes que um usuário seja marcado como on-line, para evitar quaisquer condições de corrida se a conexão de rede do cliente for perdida antes que os dois comandos possam ser enviados ao servidor.

Este é um sistema simples de presença do usuário:

// 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 = firebase.database().ref('users/joe/connections');

// stores the timestamp of my last disconnect (the last time I was seen online)
var lastOnlineRef = firebase.database().ref('users/joe/lastOnline');

var connectedRef = firebase.database().ref('.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)
    var con = myConnectionsRef.push();

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

    // Add this device to my connections list
    // this value could contain info about the device or a timestamp too
    con.set(true);

    // When I disconnect, update the last time I was seen online
    lastOnlineRef.onDisconnect().set(firebase.database.ServerValue.TIMESTAMP);
  }
});

Enviar comentários sobre…

Firebase Realtime Database
Precisa de ajuda? Acesse nossa página de suporte.