Sincronizzazione in background

Jake Archibald
Jake Archibald

Sincronizzazione in background è una nuova API web che ti consente di posticipare le azioni finché l'utente non diventa stabile e la connettività privata. In questo modo ti assicuri che l'elemento che l'utente vuole inviare venga effettivamente inviato.

Il problema

Internet è un ottimo posto per perdere tempo. Senza perdere tempo su internet, non sapremmo ai gatti non piacciono i fiori, i camaleonti amano le bolle o il nostro vero Eric Bidelman è un eroe del putt del putt della fine degli anni '90.

Ma a volte, solo qualche volta, non facciamo in modo di perdere tempo. L'utente desiderato è un po' più simile a:

  1. Il telefono è fuori dalla tasca.
  2. Raggiungi un obiettivo minimo.
  3. Smartphone di nuovo in tasca.
  4. Riprendere la vita.

Purtroppo questa esperienza viene spesso interrotta a causa di una scarsa connettività. Può capitare. Stai fissando uno schermo bianco o una ruota che gira e sai che dovresti rinunciare e andare avanti con la tua vita, ma attendi altri 10 secondi per sicurezza. Dopo quei 10 secondi? Niente.

Ma perché rinunciare ora? Hai già investito tempo, quindi andarsene senza nulla sarebbe uno spreco, quindi continua ad aspettare. A questo punto vuoi arrenderti, ma sai che nel momento in cui lo fai, è il secondo prima che tutto venisse caricato se solo tu avessi aspettato.

I service worker risolvono la parte di caricamento della pagina consentendoti di pubblicare i contenuti da una cache. E se la pagina deve inviare qualcosa al server?

Al momento, se l'utente fa clic su "Invia" su un messaggio devono fissare l'anello che gira fino al completamento. Se il cliente prova a uscire o chiudere la scheda, utilizziamo onbeforeunload per visualizzare un messaggio come "No, ho bisogno che guardi ancora la rotellina. Mi dispiace". Se l'utente non riesce a connettersi, gli comunichiamo il messaggio "Spiacenti, devi tornare più tardi e riprovare".

Questa è una schifezza. La sincronizzazione in background ti consente di fare meglio.

Soluzione

Il seguente video mostra Emojoy, una demo di chat disponibile solo con emoji. Si tratta di un'app web progressiva che funziona principalmente offline. L'app utilizza messaggi push e notifiche e la sincronizzazione in background.

Se l'utente prova a inviare un messaggio quando la connettività non è disponibile, per fortuna il messaggio viene inviato in background non appena la connettività è disponibile.

A partire da marzo 2016, la sincronizzazione in background è disponibile in Chrome a partire dalla versione 49. Per vederla, procedi nel seguente modo:

  1. Apri Emojoy.
  2. Vai offline (in modalità aereo o recati alla gabbia Faraday di zona).
  3. Digita un messaggio.
  4. Torna alla schermata Home (facoltativamente chiudi la scheda o il browser).
  5. Vai online.
  6. Il messaggio viene inviato in background.

La possibilità di inviare messaggi in background in questo modo produce anche un miglioramento percepito delle prestazioni. Non è necessario che l'app prenda in considerazione l'invio del messaggio, quindi può aggiungerlo immediatamente all'output.

Come richiedere una sincronizzazione in background

In stile web estensibile, si tratta di una di basso livello che ti dà la libertà di fare ciò che ti serve. Chiedete un da attivare quando l'utente dispone della connettività, ovvero immediatamente se l'utente dispone già di connettività. Poi ascolti quell'evento e fai qualsiasi cosa tu voglia che devono fare.

Come per i messaggi push, utilizza un service worker come target dell'evento, che lo permette di funzionare quando la pagina non è aperta. Per iniziare, registrati per una sincronizzazione da una pagina:

// 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());
  }
});

È tutto. In base a quanto riportato sopra, doSomeStuff() deve restituire una promessa che indica il successo o il fallimento di qualsiasi cosa stia cercando di fare. Se viene evaso, la sincronizzazione è completa. Se non riesce, verrà pianificata un'altra sincronizzazione per riprovare. Anche i nuovi tentativi di sincronizzazione attendono la connettività e utilizzano un backoff esponenziale.

Il nome del tag della sincronizzazione ("myFirstSync" nell'esempio riportato sopra) deve essere univoco per una determinata sincronizzazione. Se ti registri per una sincronizzazione utilizzando lo stesso tag di una sincronizzazione in attesa, questa viene unita alla sincronizzazione esistente. Ciò significa che puoi registrarti per una "casella di posta in uscita" sincronizza ogni volta che l'utente invia un messaggio. Tuttavia, se invia 5 messaggi mentre è offline, verrà eseguita una sola sincronizzazione quando saranno online. Se desideri 5 eventi di sincronizzazione separati, utilizza tag univoci.

Ecco una semplice demo che fa il minimo indispensabile: utilizza l'evento di sincronizzazione per mostrare una notifica.

A cosa serve la sincronizzazione in background?

Idealmente, dovresti usarlo per pianificare l'invio di dati che ti interessano oltre la durata della pagina. Messaggi di chat, email, aggiornamenti di documenti, modifiche alle impostazioni, caricamenti di foto... tutto ciò che vuoi raggiungere al server anche se l'utente esce dalla pagina o chiude la scheda. che potrebbero essere archiviati in una "Posta in uscita" di archiviazione in IndexDB e il service worker li recuperava e li inviava.

Tuttavia, potresti utilizzarlo anche per recuperare piccoli frammenti di dati...

Un'altra demo!

Questa è la demo di wikipedia offline che ho creato per il caricamento della pagina potenziato. Da allora ho aggiunto un po' di sincronizzazione in background.

Prova anche tu. Assicurati di utilizzare Chrome 49 o versioni successive, quindi:

  1. Vai a qualsiasi articolo, ad esempio Chrome.
  2. Vai offline (utilizzando la modalità aereo o unisciti a un operatore di telefonia mobile pessimo come me).
  3. Fai clic su un link a un altro articolo.
  4. Dovresti ricevere un avviso che il caricamento della pagina non è riuscito (questo verrà visualizzato anche se il caricamento della pagina richiede solo un po' di tempo).
  5. Accetta le notifiche.
  6. Chiudi il browser.
  7. Vai online
  8. Riceverai una notifica quando l'articolo viene scaricato, memorizzato nella cache e pronto per essere visualizzato.

Usando questo schema, l'utente può mettere il telefono in tasca e andare avanti con la propria vita, sapendo che lo smartphone li avviserà quando verrà recuperato.

Autorizzazioni

Le demo che ho mostrato utilizzano le notifiche web, che richiedono l'autorizzazione, a differenza della sincronizzazione in background.

Gli eventi di sincronizzazione spesso vengono completati finché l'utente ha una pagina aperta sul sito, quindi richiedere l'autorizzazione dell'utente sarebbe un'esperienza negativa. Stiamo invece limitando la registrazione e l'attivazione delle sincronizzazioni per prevenire comportamenti illeciti. Ad esempio:

  • Puoi registrarti a un evento di sincronizzazione solo quando l'utente ha una finestra aperta sul sito.
  • Il tempo di esecuzione dell'evento è limitato, quindi non puoi usarlo per inviare un ping a un server ogni x secondi, per estrarre bitcoin o altro.

Naturalmente, queste limitazioni potrebbero allentarsi o ridursi in base all'utilizzo reale.

Miglioramento progressivo

Ci vorrà del tempo prima che tutti i browser supportino la sincronizzazione in background, soprattutto perché Safari ed Edge non supportano ancora i service worker. Ma il miglioramento progressivo aiuta in questi casi:

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 i Service worker o la sincronizzazione in background non sono disponibili, è sufficiente pubblicare i contenuti dalla pagina, come si farebbe oggi.

È consigliabile utilizzare la sincronizzazione in background anche se l'utente sembra avere una buona connettività, in quanto ti protegge dalle navigazioni e dalla chiusura delle schede durante l'invio dei dati.

Il futuro

Il nostro obiettivo è quello di fornire la sincronizzazione in background a una versione stabile di Chrome nella prima metà del 2016, mentre lavoriamo a una variante, la "sincronizzazione periodica in background". Con una sincronizzazione periodica in background, puoi richiedere un evento limitato in base a intervallo di tempo, stato della batteria e stato della rete. Naturalmente ciò richiederebbe l'autorizzazione dell'utente e spetta al browser decidere quando e con quale frequenza vengono attivati. In altre parole, un sito di notizie potrebbe richiedere la sincronizzazione ogni ora, ma il browser potrebbe sapere che hai letto il sito solo alle 07:00, quindi la sincronizzazione si attiva ogni giorno alle 06:50. Questa idea è un po' più lontana dalla sincronizzazione una tantum, ma sta arrivando.

Un po' alla volta stiamo trasferendo sul web pattern di successo da Android e iOS, mantenendo al contempo gli elementi che rendono grande il web.