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 quiser enviar será realmente 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, Campeons adoram bolhas ou que nosso Eric Bidelman é um herói de putt de golfe do final dos anos 90.

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

  1. Smartphone fora do bolso.
  2. Atingir um objetivo menor.
  3. Smartphone de volta no bolso.
  4. Retomar vida.

Infelizmente, essa experiência é frequentemente interrompida por uma 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 continuar com sua vida, mas precisa dar mais 10 segundos, por precaução. Depois de 10 segundos? Nada

Mas por que desistir agora? Você já investiu tempo, então sair sem nada seria um desperdício, então você continua esperando. A esta altura, você quer desistir, mas sabe que o segundo em que faz isso é o segundo antes de tudo ter sido carregado se você tivesse esperado.

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

No momento, quando o usuário pressiona "enviar" em uma mensagem, ele precisa olhar para um ícone de carregamento até que ela seja concluída. Se ele tentar sair ou fechar a guia, vamos usar onbeforeunload para mostrar uma mensagem como "Não, preciso que você olhe mais um pouco para este ícone de carregamento. Desculpe". Se o usuário não tiver uma conexão, informaremos a ele "Você precisa voltar mais tarde e tentar novamente".

Isso é péssima. Com a sincronização em segundo plano, você melhora seu desempenho.

A solução

O vídeo a seguir mostra o Emojoy (link em inglês), uma demonstração de chat somente para emojis. Ele é um Progressive Web App e funciona priorizando o modo off-line. O aplicativo usa mensagens push e notificações, além de usar a sincronização em segundo plano.

Se o usuário tentar enviar uma mensagem quando não tiver conectividade, ela será enviada em segundo plano quando houver conectividade.

A partir de março de 2016, a sincronização em segundo plano está disponível no Chrome a partir da versão 49. Você pode conferir isso seguindo as etapas abaixo:

  1. Abra o Emojoy.
  2. Fique off-line (use o modo avião ou vá até sua gaiola de Faraday local).
  3. Digite uma mensagem.
  4. Volte para a tela inicial. Se quiser, feche a guia ou o navegador.
  5. Fique on-line.
  6. A mensagem é enviada em segundo plano.

Ser capaz de enviar em segundo plano dessa forma também gera uma melhoria de desempenho percebida. O app não precisa fazer muitos detalhes sobre o envio da mensagem, então ele pode adicionar a mensagem à saída imediatamente.

Como solicitar uma sincronização em segundo plano

No verdadeiro estilo de Web extensível, esse é um recurso de baixo nível que oferece liberdade para fazer o que você precisa. Você solicita que um evento seja disparado quando o usuário tiver conectividade, o que será imediato se o usuário já tiver conectividade. Em seguida, você ouve esse evento e faz o que precisa fazer.

Assim como as mensagens push, ela usa um service worker como destino do evento, o que permite que ele funcione quando a página não está aberta. Para começar, registre-se para 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. Acima, doSomeStuff() precisa retornar uma promessa que indica o sucesso/a falha de qualquer coisa que ele esteja tentando fazer. Se ela for atendida, a sincronização estará concluída. Se ela falhar, outra sincronização será programada para tentar novamente. As novas sincronizações também aguardam a conectividade e empregam uma espera exponencial.

O nome da tag da sincronização ("myFirstSync" no exemplo acima) deve ser exclusivo para uma determinada sincronização. Se você se registrar para uma sincronização usando a mesma tag de uma sincronização pendente, ela se unirá à sincronização existente. Isso significa que é possível se registrar em uma sincronização de "caixa de saída" sempre que o usuário enviar uma mensagem. No entanto, se ele enviar cinco mensagens enquanto estiver off-line, você só terá uma sincronização quando ele ficar on-line. Se você quiser cinco eventos de sincronização diferentes, basta usar tags exclusivas.

Esta é 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 seria usar esse recurso para programar o envio de dados importantes para você além da vida útil da página. Mensagens de bate-papo, e-mails, atualizações de documentos, alterações de configurações, uploads de fotos... tudo o que você quiser que chegue ao servidor, mesmo se o usuário sair ou fechar a guia. A página pode armazená-los em um armazenamento de "caixa de saída" no IndexingDB, e o service worker as recupera e os envia.

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

Outra demonstração!

Esta é a demonstração da Wikipédia off-line que criei para Sobrecarregar o carregamento de página. Desde então, adicionei um pouco de mágica de sincronização em segundo plano.

Faça um teste. Confira se você está usando a versão 49 ou mais recente do Chrome. Depois:

  1. Acesse qualquer artigo, talvez o Chrome.
  2. Fique off-line (use o modo avião ou entre em uma operadora de celular ruim como a minha).
  3. Clique em um link para outro artigo.
  4. Você vai receber um aviso de falha no carregamento da página. Essa informação também aparece se o carregamento da página demorar.
  5. Concorde com as notificações.
  6. Feche o navegador.
  7. Modo on-line
  8. Você vai receber uma notificação quando a matéria for transferida por download, armazenada em cache e estiver pronta para visualização.

Com esse padrão, o usuário pode colocar o smartphone no bolso e seguir com a vida sabendo que o smartphone o alertará quando for buscado, assim que ele quiser.

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 exige.

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

  • Só é possível se registrar em 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á-lo para dar um ping em um servidor a cada x segundos, minerar bitcoins ou qualquer outra coisa.

Obviamente, essas restrições podem ser menores ou menores com base no uso real.

Aprimoramento progressivo

Vai demorar um pouco para que todos os navegadores ofereçam suporte à sincronização em segundo plano, principalmente porque o Safari e o Edge ainda não são compatíveis com 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, basta postar o conteúdo da página como faria hoje.

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

O futuro

Nosso objetivo é lançar a sincronização em segundo plano para uma versão estável do Chrome na primeira metade de 2016, enquanto trabalhamos em uma variante, a "sincronização periódica em segundo plano". Com a sincronização periódica em segundo plano, você pode solicitar um evento restrito por intervalo de tempo, estado da bateria e da rede. Obviamente, isso exigiria a permissão do usuário, e também depende do navegador de quando e com que frequência esses eventos são disparados. 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, então a sincronização seria disparada diariamente às 6h50. Essa ideia está um pouco mais longe do que a sincronização única, mas ela está chegando.

Pouco a pouco, estamos trazendo padrões de sucesso do Android e do iOS para a Web, sem deixar de manter o que torna a Web incrível.