Task Scheduling
There is no generic task scheduler available for the Web applications as of early 2020. There are however few active attempts to solve the most prominent use cases for scheduler, separately.
The first proposal is called Periodic Background Sync API and it addresses the background data synchronization use case. It complements the Background Sync capability. It allows the Web applications to register for the periodic event that causes the Service Worker to be woken up and make it possible to execute HTTP request without user interaction. The API, as of early 2020, is experimentally available in Google Chrome 80+ only and its usage is restricted to installed applications with high enough engagement score. The API does not guarantee the interval of the synchronization – it allows requesting minimum interval via minInterval
parameter, although to avoid abuse, the actual interval is dependent on the number of factors such as the network trustworthiness and the frequency the user uses the app.
The second proposal is called Notification Trigger API. It is an extension to the existing Notifications API that allows the local notification to be deferred and scheduled to be shown according to the external trigger – i.e. time- or location-based. The notification needs to be pre-created and the API doesn't allow any code to be executed at the trigger. The API is only available in Google Chrome 80+ via Origin Trial experimentation and as of early 2020 is limited to time-based triggers.
Historically, the earliest attempt to provide the Web applications an ability to be activated according to the system-level scheduler was called Web Alarms API. It was abandoned in 2013 in favor of the newer Task Scheduler API proposal based on Service Worker primitives that in turn was abandoned as too generic and open for abuse. Its idea was to act as a wrapper for the underlying operating system scheduler and allow authorized Web applications implementing broad scenarios such as alarms, reminders or periodic data synchronization. It was supposed to wake up the system at the specific time or in the first possible moment after the scheduled time and run the user-defined handler within the Service Worker instance.
API glimpse
Periodic Background Sync API (experimental)
navigator.serviceWorker.getRegistration()
.then((reg) => reg.periodicSync.register(tag, {minInterval}))
- Requests an event to be triggered within the Service Worker instance at the specified minimum interval
minInterval
with the specifiedtag
. reg.periodicSync.getTags()
- Returns a
Promise
resolved with the sync requests already registered by the current application. self.addEventListener('periodicsync', listener)
- An event fired within the Service Worker periodically (at the browser-controlled interval) with the
tag
, allowing data fetch.
Notification Trigger API (experimental)
const trigger = new TimestampTrigger(timestamp)
- Creates a time-based trigger that will activate on a given
timestamp
. navigator.serviceWorker.getRegistration()
.then((reg) => reg.showNotification(title, {...options, showTrigger: trigger}))
- Schedules a local notification to be shown from within the Service Worker based on the
trigger
. For other Notification options, see Local Notifications.
Web Alarms API (never implemented)
navigator.serviceWorker.getRegistration()
.then((reg) => reg.taskScheduler.add(time, [data]))
- Schedules an event to be triggered within the Service Worker instance at the specified
time
with the specifieddata
payload. reg.taskScheduler.getPendingTasks()
- Returns a
Promise
resolved with the events already scheduled by the current application. self.addEventListener('task', listener)
- An event fired within the Service Worker at the scheduled time (or as soon as it is possible after) with the
task
data.
Live Demo
-
function scheduleNotification() { if (!('Notification' in window)) { alert('Notification API not supported'); return; } if (!('showTrigger' in Notification.prototype)) { alert('Notification Trigger API not supported'); return; } Notification.requestPermission() .then(() => { if (Notification.permission !== 'granted') { throw 'Notification permission is not granted'; } }) .then(() => navigator.serviceWorker.getRegistration()) .then((reg) => { reg.showNotification("Hi there from the past!", { showTrigger: new TimestampTrigger(new Date().getTime() + 10 * 1000) }) }) .catch((err) => { alert('Notification Trigger API error: ' + err); }); }
-
<p><button onclick="scheduleNotification()">Schedule notification in 10s<br>(using Notification Trigger API)</button></p>