Quando você envia dados para um servidor da Web, às vezes as solicitações falham. Isso pode ocorrer porque o usuário perdeu a conectividade ou porque o servidor está inativo. Em ambos os casos, tente enviar as solicitações novamente mais tarde.
A nova API BackgroundSync
é a solução ideal para esse problema. Quando um service worker detecta que uma solicitação de rede falhou, ele pode se registrar para receber um evento sync
, que é entregue quando o navegador acredita que a conectividade retornou.
O evento de sincronização pode ser enviado mesmo que o usuário tenha saído do
aplicativo, o que o torna muito mais eficaz do que o método tradicional de
repetição de solicitações com falha.
A sincronização em segundo plano do Workbox foi criada para facilitar o uso da API BackgroundSync e a integração com outros módulos do Workbox. Ela também implementa uma estratégia substituta para navegadores que ainda não implementam BackgroundSync.
Os navegadores compatíveis com a API BackgroundSync vão reproduzir automaticamente as solicitações com falha em seu nome em um intervalo gerenciado pelo navegador, provavelmente usando espera exponencial entre as tentativas de repetição. Em navegadores que não oferecem suporte nativo à API BackgroundSync, o Workbox Background Sync tentará uma repetição automaticamente sempre que o service worker for iniciado.
Uso básico
A maneira mais fácil de usar a sincronização em segundo plano é usar a Plugin
, que automaticamente enfileira as solicitações com falha e as repete quando eventos sync
futuros são disparados.
import {BackgroundSyncPlugin} from 'workbox-background-sync';
import {registerRoute} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';
const bgSyncPlugin = new BackgroundSyncPlugin('myQueueName', {
maxRetentionTime: 24 * 60, // Retry for max of 24 Hours (specified in minutes)
});
registerRoute(
/\/api\/.*\/*.json/,
new NetworkOnly({
plugins: [bgSyncPlugin],
}),
'POST'
);
BackgroundSyncPlugin
hooks no
callback do plug-in fetchDidFail
, e
fetchDidFail
só será invocado se houver uma exceção gerada, provavelmente devido
a uma falha de rede. Isso significa que as solicitações não serão repetidas se houver uma
resposta recebida com um
status de erro 4xx
ou 5xx
.
Se você quiser repetir todas as solicitações que resultam em, por exemplo, um status 5xx
,
adicione um plug-in fetchDidSucceed
à sua estratégia:
const statusPlugin = {
fetchDidSucceed: ({response}) => {
if (response.status >= 500) {
// Throwing anything here will trigger fetchDidFail.
throw new Error('Server error.');
}
// If it's not 5xx, use the response as-is.
return response;
},
};
// Add statusPlugin to the plugins array in your strategy.
Uso avançado
A sincronização em segundo plano da caixa de trabalho também fornece uma classe Queue
, que é possível
instanciar e adicionar solicitações com falha. As solicitações com falha são armazenadas
no IndexedDB
e são repetidas quando o navegador acha que a conectividade foi restaurada (ou seja,
quando recebe o evento de sincronização).
Como criar uma fila
Para criar uma fila de sincronização em segundo plano da Workbox, crie-a com um nome de fila, que precisa ser exclusivo para sua origin:
import {Queue} from 'workbox-background-sync';
const queue = new Queue('myQueueName');
O nome da fila é usado como parte do nome da tag que recebe a codificação register()
pela SyncManager
global. Ele
também é usado como o nome do
Object Store para
o banco de dados IndexedDB.
Como adicionar uma solicitação à fila
Depois de criar sua instância Queue, é possível adicionar solicitações com falha a ela.
Adicione uma solicitação com falha invocando o método .pushRequest()
. Por exemplo,
o código a seguir captura todas as solicitações que falham e as adiciona à fila:
import {Queue} from 'workbox-background-sync';
const queue = new Queue('myQueueName');
self.addEventListener('fetch', event => {
// Add in your own criteria here to return early if this
// isn't a request that should use background sync.
if (event.request.method !== 'POST') {
return;
}
const bgSyncLogic = async () => {
try {
const response = await fetch(event.request.clone());
return response;
} catch (error) {
await queue.pushRequest({request: event.request});
return error;
}
};
event.respondWith(bgSyncLogic());
});
Depois de adicionada à fila, a solicitação é repetida automaticamente quando o
service worker recebe o evento sync
, que acontece quando o navegador
pensa que a conectividade foi restaurada. Os navegadores que não oferecem suporte à
API BackgroundSync vão tentar enviar a fila novamente toda vez que o service worker for
iniciado. Isso exige que a página que controla o service worker esteja
em execução, então não será tão eficaz.
Testar a sincronização em segundo plano da caixa de trabalho
Infelizmente, o teste do BackgroundSync é um pouco pouco intuitivo e difícil por vários motivos.
A melhor abordagem para testar a implementação é fazer o seguinte:
- Carregue uma página e registre o service worker.
- Desative a rede do computador ou o servidor da Web.
- NÃO USE O GOOGLE DEVTOOLS OFF-LINE. A caixa de seleção off-line no DevTools só afeta solicitações da página. As solicitações do Service Worker continuarão a ser processadas.
- Faça solicitações de rede que precisam ser enfileiradas com a sincronização em segundo plano do Workbox.
- É possível verificar se as solicitações foram colocadas na fila consultando
Chrome DevTools > Application > IndexedDB > workbox-background-sync > requests
- É possível verificar se as solicitações foram colocadas na fila consultando
- Agora, ative a rede ou o servidor da Web.
Para forçar um evento
sync
antecipado, acesseChrome DevTools > Application > Service Workers
, insira o nome da tag deworkbox-background-sync:<your queue name>
, em que<your queue name>
deve ser o nome da fila definida, e clique no botão "Sincronizar".Você verá as solicitações de rede serem transmitidas para as solicitações com falha, e os dados do IndexedDB estarão vazios, já que as solicitações foram repetidas com sucesso.
Tipos
BackgroundSyncPlugin
Uma classe que implementa o callback do ciclo de vida fetchDidFail
. Isso facilita
a adição de solicitações com falha a uma fila de sincronização em segundo plano.
Propriedades
-
construtor
void
A função
constructor
tem esta aparência:(name: string, options?: QueueOptions) => {...}
-
name
string
Consulte a documentação
workbox-background-sync.Queue
para ver detalhes do parâmetro. -
opções
QueueOptions opcional
-
retorna
-
Queue
Uma classe para gerenciar o armazenamento de solicitações com falha no IndexedDB e tentar novamente mais tarde. Todas as partes do processo de armazenamento e repetição podem ser observadas com callbacks.
Propriedades
-
construtor
void
Cria uma instância de Queue com as opções fornecidas
A função
constructor
tem esta aparência:(name: string, options?: QueueOptions) => {...}
-
name
string
O nome exclusivo dessa fila. Esse nome precisa ser exclusivo porque é usado para registrar eventos de sincronização e armazenar solicitações no IndexedDB específicas para essa instância. Um erro será gerado se um nome duplicado for detectado.
-
opções
QueueOptions opcional
-
retorna
-
-
name
string
-
getAll
void
Retorna todas as entradas que não expiraram (por
maxRetentionTime
). Todas as entradas expiradas são removidas da fila.A função
getAll
tem esta aparência:() => {...}
-
retorna
Promise<QueueEntry[]>
-
-
popRequest
void
Remove e retorna a última solicitação na fila, com o carimbo de data/hora e todos os metadados. O objeto retornado tem a forma:
{request, timestamp, metadata}
.A função
popRequest
tem esta aparência:() => {...}
-
retorna
Promise<QueueEntry>
-
-
pushRequest
void
Armazena a solicitação passada no IndexedDB (com o carimbo de data/hora e quaisquer metadados) no final da fila.
A função
pushRequest
tem esta aparência:(entry: QueueEntry) => {...}
-
entry
QueueEntry
-
retorna
Promise<void>
-
-
registerSync
void
Registra um evento de sincronização com uma tag exclusiva para esta instância.
A função
registerSync
tem esta aparência:() => {...}
-
retorna
Promise<void>
-
-
replayRequests
void
Percorra cada solicitação na fila e tenta buscá-la novamente. Se uma solicitação não for buscada novamente, ela será colocada de volta na mesma posição na fila, que registra uma nova tentativa para o próximo evento de sincronização.
A função
replayRequests
tem esta aparência:() => {...}
-
retorna
Promise<void>
-
-
shiftRequest
void
Remove e retorna a primeira solicitação na fila, com o carimbo de data/hora e todos os metadados. O objeto retornado tem a forma:
{request, timestamp, metadata}
.A função
shiftRequest
tem esta aparência:() => {...}
-
retorna
Promise<QueueEntry>
-
-
tamanho
void
Retorna o número de entradas presentes na fila. As entradas expiradas (por
maxRetentionTime
) também são incluídas nessa contagem.A função
size
tem esta aparência:() => {...}
-
retorna
Prometer<número>
-
-
unshiftRequest
void
Armazena a solicitação transmitida no IndexedDB (com o carimbo de data/hora e quaisquer metadados) no início da fila.
A função
unshiftRequest
tem esta aparência:(entry: QueueEntry) => {...}
-
entry
QueueEntry
-
retorna
Promise<void>
-
QueueOptions
Propriedades
-
forceSyncFallback
booleano opcional
-
maxRetentionTime
número opcional
-
onSync
OnSyncCallback opcional
QueueStore
Uma classe para gerenciar solicitações de armazenamento de uma fila no IndexedDB, indexadas pelo nome da fila para facilitar o acesso.
A maioria dos desenvolvedores não precisa acessar essa classe diretamente. Ela fica exposta para casos de uso avançados.
Propriedades
-
construtor
void
Associa essa instância a uma instância Queue. Assim, as entradas adicionadas podem ser identificadas pelo nome da fila.
A função
constructor
tem esta aparência:(queueName: string) => {...}
-
queueName
string
-
retorna
-
-
deleteEntry
void
Exclui a entrada do ID fornecido.
AVISO: esse método não garante que a entrada excluída pertença a essa fila (ou seja, corresponde a
queueName
). Mas essa limitação é aceitável porque essa classe não está exposta publicamente. Uma verificação extra tornaria esse método mais lento do que deveria.A função
deleteEntry
tem esta aparência:(id: number) => {...}
-
id
number
-
retorna
Promise<void>
-
-
getAll
void
Retorna todas as entradas na loja que correspondem a
queueName
.A função
getAll
tem esta aparência:() => {...}
-
retorna
Promise<QueueStoreEntry[]>
-
-
popEntry
void
Remove e retorna a última entrada na fila que corresponde ao
queueName
.A função
popEntry
tem esta aparência:() => {...}
-
retorna
Promise<QueueStoreEntry>
-
-
pushEntry
void
Anexar uma entrada por último na fila.
A função
pushEntry
tem esta aparência:(entry: UnidentifiedQueueStoreEntry) => {...}
-
entry
UnidentifiedQueueStoreEntry
-
retorna
Promise<void>
-
-
shiftEntry
void
Remove e retorna a primeira entrada na fila que corresponde ao
queueName
.A função
shiftEntry
tem esta aparência:() => {...}
-
retorna
Promise<QueueStoreEntry>
-
-
tamanho
void
Retorna o número de entradas na loja que correspondem a
queueName
.A função
size
tem esta aparência:() => {...}
-
retorna
Prometer<número>
-
-
unshiftEntry
void
Incluir uma entrada no início da fila.
A função
unshiftEntry
tem esta aparência:(entry: UnidentifiedQueueStoreEntry) => {...}
-
entry
UnidentifiedQueueStoreEntry
-
retorna
Promise<void>
-
StorableRequest
Uma classe para facilitar a serialização e desserialização de solicitações para que elas possam ser armazenadas no IndexedDB.
A maioria dos desenvolvedores não precisa acessar essa classe diretamente. Ela fica exposta para casos de uso avançados.
Propriedades
-
construtor
void
Aceita um objeto de dados de solicitação que pode ser usado para construir um
Request
, mas que também pode ser armazenado no IndexedDB.A função
constructor
tem esta aparência:(requestData: RequestData) => {...}
-
requestData
RequestData
Um objeto de dados de solicitação que inclui
url
e todas as propriedades relevantes de [requestInit]https://fetch.spec.whatwg.org/#requestinit
.
-
retorna
-
-
clone
void
Cria e retorna um clone profundo da instância.
A função
clone
tem esta aparência:() => {...}
-
retorna
-
-
toObject
void
Retorna um clone profundo do objeto
_requestData
das instâncias.A função
toObject
tem esta aparência:() => {...}
-
retorna
RequestData
-
-
toRequest
void
Converte esta instância em uma solicitação.
A função
toRequest
tem esta aparência:() => {...}
-
retorna
Solicitação
-
-
fromRequest
void
Converte um objeto de solicitação em um objeto simples que pode ser estruturado clonado ou strings em JSON.
A função
fromRequest
tem esta aparência:(request: Request) => {...}
-
request
Solicitação
-
retorna
Promise<StorableRequest>
-