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 será mais ou menos assim:
- O smartphone está fora do bolso.
- Atingir um objetivo menor.
- O smartphone está no bolso.
- 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 apenas desistir e seguir com sua vida, mas precisa dar mais 10 segundos, caso precise. 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ê exiba o 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 fazer melhor.
A solução
O vídeo a seguir mostra Emojoy, um chat de demonstração apenas de 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.
A partir de 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:
- Abra o Emojoy.
- Desconecte-se (usando o modo avião ou visitando sua gaiola de Faraday local).
- Digite uma mensagem.
- Volte para a tela inicial (ou feche a guia ou o navegador).
- Acesse a Internet.
- 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 verdadeiro da Web extensível, esse é um recurso de baixo nível que oferece 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 nas 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 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 importantes para você além da vida útil da página. Mensagens de chat, e-mails, atualizações de documentos, mudanças 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 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 Aumento da velocidade de carregamento da página. Depois disso, adicionei um toque mágico de sincronização em segundo plano.
Faça um teste. Verifique se você está usando o Chrome 49 ou uma versão mais recente e faça o seguinte:
- Acesse qualquer artigo, talvez o Chrome.
- Fique off-line, usando o modo avião ou junte-se a uma péssima operadora de celular como a minha.
- Clique em um link para outro artigo.
- 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.
- Concordar com as notificações.
- Feche o navegador.
- Modo on-line
- Você vai receber uma notificação quando o artigo for transferido por download, armazenado em cache e estiver 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 apresentadas 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:
- Você só pode se registrar em um evento de sincronização quando o usuário está com uma janela aberta no site.
- O tempo de execução do evento é limitado, portanto não é possível usá-los para dar ping em um servidor a cada x segundos, minerar bitcoins ou qualquer outra coisa.
É 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, basta publicar o conteúdo da página, como você 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 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ê o site às 7h, de modo que a sincronização é acionada diariamente às 6h50. Essa ideia está um pouco mais distante do que uma sincronização única, mas está a caminho.
Aos poucos, estamos trazendo padrões bem-sucedidos do Android e do iOS para a Web, mantendo o que torna a Web incrível.