Service Workers – Part 4 – Background Sync

Hi there fellas…rollin’ on in our series on Service Workers, today we will see how to run background synchronization tasks using them. We’ll do a small demo to get a better understanding. Let’s get straight to it.


As of this writing only one time sync works, that too in Chrome Canary behind a developer flag. Periodic syncs are not yet supported.

You can see a live demo here. The repository for the demo is available here.

Before starting off, make sure to have local HTTP server running as Service Workers don’t work on file protocol. Install node. Check this link to find out how to install node and npm. Then install http-server node module for the HTTP server.

What is Background Synchronization?

Background synchronization as the same suggests are tasks that run in the background. So how would they be helpful?

In areas where internet connectivity is not great or consistent, it is difficult for websites to remain in sync with their servers. Users might be working on something and suddenly internet connectivity is lost. If the browser is closed or the user navigates away before synchronization can complete, the app must wait until the user revisits the page to try again.

In such cases, when connectivity comes back, background synchronizations allow you to contact and sync the data with the server in the background, even though the user has left the website.

There are two types of background synchronizations:

  • One Time Synchronization – Executes only once per registration of the sync task
  • Periodic Synchronization – Executes at least once for every minimum interval specified during the registration

As of this writing, background sync’s are supported only in Chrome Canary. So make sure to download it. You can check the status of whether background syncs have been shipped to Chrome here.

After you have downloaded and installed Chrome Canary, type chrome://flags in the address bar. In the page that appears, look for experimental-web-platform-features and enable it. Now restart Canary.

Let’s get started with the Demo. Create the following files: index.html, script.js, sw.js

Setting up the UI

In our demo UI, we will have two buttons. One to subscribe for one time sync and the other for Periodic sync.

index.html
<!DOCTYPE html>
<html>

<head>
 <title> Service Workers - Background Sync</title>
 <script type="text/javascript" src="script.js">< /script>
</head>

<body>
 <button type="button" onclick="registerOneTimeSync()">Request for One Time Sync</button>
 <button type="button" onclick="registerPeriodicSync()">Register For Periodic Sync</button>
</body>

</html>

Registering the Service Worker

First thing, we have to register the Service Worker.

script.js
 if (navigator.serviceWorker) {
   console.log("ServiceWorkers are supported");

   navigator.serviceWorker.register('sw.js', {
     scope: './'
   })
   .then(function(reg) {
     console.log("ServiceWorker registered", reg);
   })
   .catch(function(error) {
     console.log("Failed to register ServiceWorker", error);
   });
}

Here we go through the usual routine of checking whether the Service Worker is supported. Then we register the Service Worker.

Register One Time Sync

First up, we will do one time sync.

script.js
function registerOneTimeSync() {
    if (navigator.serviceWorker.controller) {
        navigator.serviceWorker.ready.then(function(reg) {
            if (reg.sync) {
                reg.sync.register('oneTimeSync')
                    .then(function(event) {
                        console.log('Sync registration successful', event);
                    })
                    .catch(function(error) {
                        console.log('Sync registration failed', error);
                    });
            } else {
                console.log("Onw time Sync not supported");
            }
        });
    } else {
        console.log("No active ServiceWorker");
    }
}

Here, we first whether the page is in control of a service worker and if so, we check whether it is activated and ready. Background synchronization registrations can be made only when the Service Worker are activated.

We then call register on the reg.sync instance with a tag. Tags are meant for uniqueness among sync tasks. If a sync task with the same tag exists, then that task instance will be returned, if not a new one will be created.

If there’s no active window open for the origin, registration will fail. That’s why we have registered for sync from the page rather than from the activate event of the Service Worker itself.

Event Handler for One Time Sync

Now, we will register the event handler that will be invoked when the sync event fires.

sw.js
self.addEventListener('sync', function(event) {
    if (event.tag == "oneTimeSync") {
        console.log('One Time Sync event fired: ', self.registration);
    }
});

Here, we attach an event listener to the sync event, which just prints that it was invoked.

One Time Sync in Action

To see one time sync in action. Do the following:

    • Disconnect Wi-Fi on you laptop
    • Click on the One Time Sync button. Make sure the registration is successful.
    • Now turn the Wi-Fi back on. You will see that the function we attached to the sync will be invoked as soon as internet is back on.

See this video for a demo :

The video shows how the background task is fired even though the site is closed altogether.

Register Periodic Sync

For periodic sync, we have to register for periodic sync and also attach an event listener to the periodic sync event. The different options possible for the sync event are:

script.js
function registerPeriodicSync() {
    if (navigator.serviceWorker.controller) {
        navigator.serviceWorker.ready.then(function(reg) {
            if (reg.periodicSync) {
                reg.periodicSync.register({
                        tag: 'periodicSync',
                        minPeriod: 0,
                        powerState: 'auto',
                        networkState: 'any'
                    })
                    .then(function(event) {
                        console.log('Periodic Sync registration successful', event);
                    })
                    .catch(function(error) {
                        console.log('Periodic Sync registration failed', error);
                    });
            } else {
                console.log("Background Sync not supported");
            }
        });
    } else {
        console.log("No active ServiceWorker");
    }
}

Again Periodic Sync can be registered only with an active Service Worker. So first we check for an active service worker. Then we register for the the periodic sync event.

tag Gives uniqueness to each registration. If one exists, it gets replaced.
minPeriod The minimum time interval between synchronizations. Specified in milliseconds. 0 means, the UI may fire the event as frequently as it wishes. This value is a suggestion to prevent over-syncing
powerState auto(default) or avoid draining. ‘auto’ means sync occurs during battery drain, whereas ‘avoid draining’ delays syncing till charging
networkState online(default)/avoid-cellular/any. ‘avoid-cellular’ will delay syncs if the device is on a cellular connection – but be aware that some users may never use another connection type. “online” will delay syncs if the device is online, although the UA may choose to avoid particular connection types depending on global device status (such as roaming) or user preferences. “any” is similar to “online”, except syncs may happen while the device is offline.

Event Handler for Periodic Sync

Now we need to attach a function that will be invoked on periodic sync.

sw.js
self.addEventListener('periodicsync', function(event) {
    if (event.registration.tag == "periodicSync") {
        console.log("Periodic sync event occurred: ", event);
    }
});

The above function just prints out to the console when invoked.

For periodic syncs, since it is scheduled by the UI we cannot be sure of when it will be invoked. All we can do it to register for it with a minimum time interval and wait for it to be invoked.

We’re done with background synchronization using Service Wokers guys. If you have any questions, leave them in the comments below. See you in the next one.. Peace.. 🙂

Leave a comment