Apresentamos a Sincronização em segundo plano

Jake Archibald
Jake Archibald

A sincronização em segundo plano é uma nova API da Web que permite adiar ações até que o usuário tenha uma conectividade estável. Isso garante que tudo o que o usuário quer enviar seja enviado.

O problema

A Internet é um ótimo lugar para perder tempo. Sem perder tempo na Internet, não saberíamos que gatos não gostam de flores, que camaleões adoram bolhas ou que nosso próprio Eric Bidelman é um herói do minigolfe dos anos 90.

Mas às vezes, só às vezes, não queremos perder tempo. A experiência do usuário desejada é mais parecida com esta:

  1. O smartphone está fora do bolso.
  2. Alcançar a meta secundária.
  3. O smartphone está no bolso.
  4. Retomar a vida.

Infelizmente, essa experiência é frequentemente interrompida pela conectividade ruim. Todos nós já passamos por isso. Você está olhando para uma tela branca ou um ícone de carregamento e sabe que deveria desistir e seguir em frente, mas espera mais 10 segundos por precaução. Após esses 10 segundos? Nada

Mas por que desistir agora? Você já investiu tempo, então sair sem nada seria um desperdício. Por isso, você continua esperando. Nesse ponto, você quer desistir, mas sabe que, se fizer isso, será o segundo antes de tudo ser carregado se você tivesse esperado.

Os service workers resolvem a parte de carregamento da página, permitindo que você forneça conteúdo de um cache. Mas e quando a página precisa enviar algo para o servidor?

No momento, se o usuário clicar em "enviar" em uma mensagem, ele terá que olhar para um ícone de carregamento até que a mensagem seja enviada. Se o usuário tentar sair ou fechar a guia, usaremos onbeforeunload para mostrar uma mensagem como "Não, preciso que você olhe para este indicador por mais um tempo. Desculpe". Se o usuário não tiver conexão, vamos informar "Lamentamos, você precisa voltar mais tarde e tentar novamente".

Isso é uma bobagem. A sincronização em segundo plano permite que você faça melhor.

A solução

O vídeo a seguir mostra o Emojoy, uma demonstração de chat com emojis. É um App Web Progressivo e funciona off-line. O app usa notificações e mensagens push, além da sincronização em segundo plano.

Se o usuário tentar enviar uma mensagem sem conectividade, a mensagem será enviada em segundo plano quando a conectividade for restabelecida.

Desde março de 2016, a Sincronização em segundo plano está disponível no Chrome a partir da versão 49. Para conferir, siga as etapas abaixo:

  1. Abra o Emojoy.
  2. Desconecte-se da rede (usando o modo avião ou visitando sua gaiola de Faraday local).
  3. Digite uma mensagem.
  4. Volte para a tela inicial (ou feche a guia ou o navegador).
  5. Acesse a Internet.
  6. A mensagem é enviada em segundo plano.

A capacidade de enviar em segundo plano também resulta em uma melhoria de desempenho percebida. O app não precisa se preocupar tanto com o envio de mensagens, então ele pode adicionar a mensagem à saída imediatamente.

Como solicitar uma sincronização em segundo plano

No estilo da Web extensível, esse é um recurso de baixo nível que dá a liberdade de fazer o que você precisa. Você pede que um evento seja acionado quando o usuário tem conectividade, o que é imediato se o usuário já tiver conectividade. Em seguida, você detecta esse evento e faz o que precisa.

Assim como as mensagens push, ele usa um service worker como o destino do evento, o que permite que ele funcione quando a página não está aberta. Para começar, registre uma sincronização em uma página:

// Register your service worker:
navigator.serviceWorker.register('/sw.js');

// Then later, request a one-off sync:
navigator.serviceWorker.ready.then(function(swRegistration) {
  return swRegistration.sync.register('myFirstSync');
});
 ```

Then listen for the event in `/sw.js`:

```js
self.addEventListener('sync', function(event) {
  if (event.tag == 'myFirstSync') {
    event.waitUntil(doSomeStuff());
  }
});

Pronto. No exemplo acima, doSomeStuff() precisa retornar uma promessa indicando o sucesso/falha do que está tentando fazer. Se ela for atendida, a sincronização será concluída. Se ela falhar, outra sincronização será programada para tentar novamente. As novas tentativas de sincronização também aguardam a conectividade e usam uma espera exponencial.

O nome da tag da sincronização ("myFirstSync" no exemplo acima) precisa ser exclusivo para uma determinada sincronização. Se você se inscrever para uma sincronização usando a mesma tag de uma sincronização pendente, ela será mesclada com a sincronização atual. Isso significa que você pode se registrar para uma sincronização "clear-outbox" sempre que o usuário enviar uma mensagem, mas se ele enviar cinco mensagens enquanto estiver off-line, você só vai receber uma sincronização quando ele estiver on-line. Se você quiser cinco eventos de sincronização separados, use tags exclusivas.

Confira uma demonstração simples que faz o mínimo necessário. Ela usa o evento de sincronização para mostrar uma notificação.

Para que posso usar a sincronização em segundo plano?

O ideal é usá-lo para programar o envio de dados que você quer além da vida útil da página. Mensagens de chat, e-mails, atualizações de documentos, alterações de configurações, uploads de fotos... tudo o que você quiser que chegue ao servidor, mesmo que o usuário saia ou feche a guia. A página poderia armazená-los em uma "caixa de saída" no indexedDB, e o service worker os recuperaria e os enviaria.

No entanto, você também pode usá-lo para buscar pequenos pedaços de dados...

Mais uma demonstração!

Esta é a demonstração da Wikipédia off-line que criei para Carregar a página com mais rapidez. Desde então, adicionei um pouco de magia à sincronização em segundo plano.

Teste por conta própria. Verifique se você está usando o Chrome 49 ou uma versão mais recente e faça o seguinte:

  1. Acesse qualquer artigo, talvez o Chrome.
  2. Desligue a conexão (usando o modo avião ou se inscrevendo em um provedor de celular ruim, como eu).
  3. Clicar em um link para outro artigo.
  4. Você vai receber uma mensagem informando que a página não foi carregada. Isso também vai aparecer se a página demorar um pouco para carregar.
  5. Concordar com as notificações.
  6. Feche o navegador.
  7. Modo on-line
  8. Você vai receber uma notificação quando o artigo for baixado, armazenado em cache e pronto para visualização.

Usando esse padrão, o usuário pode colocar o smartphone no bolso e continuar a vida, sabendo que o smartphone vai alertá-lo quando o que ele queria for buscado.

Permissões

As demonstrações que mostrei usam notificações da Web, que exigem permissão, mas a sincronização em segundo plano não.

Os eventos de sincronização geralmente são concluídos enquanto o usuário tem uma página aberta para o site. Portanto, exigir a permissão do usuário seria uma experiência ruim. Em vez disso, estamos limitando quando as sincronizações podem ser registradas e acionadas para evitar abusos. Exemplo:

  • Só é possível se registrar para um evento de sincronização quando o usuário tem uma janela aberta para o site.
  • O tempo de execução do evento é limitado, então não é possível usá-los para fazer ping em um servidor a cada x segundos, minerar bitcoins ou o que for.

É claro que essas restrições podem ser flexibilizadas ou endurecidas com base no uso real.

Aprimoramento progressivo

Vai demorar um pouco até que todos os navegadores ofereçam suporte à sincronização em segundo plano, especialmente porque o Safari e o Edge ainda não oferecem suporte a service workers. Mas o aprimoramento progressivo ajuda aqui:

if ('serviceWorker' in navigator && 'SyncManager' in window) {
  navigator.serviceWorker.ready.then(function(reg) {
    return reg.sync.register('tag-name');
  }).catch(function() {
    // system was unable to register for a sync,
    // this could be an OS-level restriction
    postDataFromThePage();
  });
} else {
  // serviceworker/sync not supported
  postDataFromThePage();
}

Se os service workers ou a sincronização em segundo plano não estiverem disponíveis, publique o conteúdo da página como faria hoje.

Vale a pena usar a sincronização em segundo plano, mesmo que o usuário pareça ter boa conectividade, porque ela protege você contra navegações e fechamentos de guias durante o envio de dados.

O futuro

Nosso objetivo é enviar a sincronização em segundo plano para uma versão estável do Chrome no primeiro semestre de 2016, enquanto trabalhamos em uma variante, a "sincronização periódica em segundo plano". Com a sincronização periódica em segundo plano, é possível solicitar um evento restrito por intervalo de tempo, estado da bateria e estado da rede. Isso exigiria a permissão do usuário, é claro, e também caberia ao navegador definir quando e com que frequência esses eventos são acionados. Em outras palavras, um site de notícias pode solicitar a sincronização a cada hora, mas o navegador pode saber que você só lê esse site às 7h. Assim, a sincronização é acionada diariamente às 6h50. Essa ideia está um pouco mais distante da sincronização única, mas está chegando.

Aos poucos, estamos trazendo padrões bem-sucedidos do Android e do iOS para a Web, mantendo o que torna a Web incrível.