For other translations in this series, see JS Working Mechanism – Xiaobai 1991 column – Nuggets (juejin.cn).

Push is pretty common on mobile, but it’s surprisingly late on the Web, even though developers have been calling for it for a long time.

An overview of the

Web push mechanism, allowing users to choose to update the app regularly. It aims to reacquire interesting, important and timely information for users.

Push is based on the Service Worker.

The reason to use Service workers is that they execute in the background. This is important for push messages because it means that the code for a push notification is executed only when the user interacts with the push notification itself.

Push & Notification

Push and notification are different apis:

  • Push – triggered when the server sends information to the Service Worker
  • Notification— This is the Service Worker or a script that pushes information to the user.

push

There are three steps to implementing push

  1. UI – Add necessary client logical subscribers for push. Write JavaScript code logic in the web application interface to get users to sign up for the push service.
  2. Send push Messages – API calls implemented by the server to push messages to the user’s device
  3. Receive message – When the browser receives the message, it processes it

More details later

Compatibility check

First, we need to check if the current browser supports push notifications. We can detect this in two steps:

  1. checknavigatorObject hasserviceWorker
  2. checkwindowObject hasPushManager

It looks like this:

if (! ('serviceWorker' in navigator)) { // Service Worker isn't supported on this browser, disable or hide UI. return; } if (! ('PushManager' in window)) { // Push isn't supported on this browser, disable or hide UI. return; }Copy the code

Registration Service Worker

At this point, we know that this feature is supported. The next step is to sign up for our Service Woker. You may already be familiar with this process

Request permission to

After a Service Worker has been registered, we can proceed with subscribing the user. To do so, We need to get his permission to send him push messages. In order to do this, we need to get the right to push information to the user. The API for obtaining permissions is very simple, but it has a downside. Instead of calling back, the API returns a Promise. This introduces the problem that we don’t know which version the current browser implements, so we need to implement both.

Like this:

function requestPermission() { return new Promise(function(resolve, reject) { const permissionResult = Notification.requestPermission(function(result) { // Handling deprecated version with  callback. resolve(result); }); if (permissionResult) { permissionResult.then(resolve, reject); } }) .then(function(permissionResult) { if (permissionResult ! == 'granted') { throw new Error('Permission not granted.'); }}); }Copy the code

Call Notification. RequestPermission () will give the user according to this

When a permission request is granted, turned off, or blocked, we give the corresponding string ‘granted’, ‘default’ or ‘denied’

If the user clicks a Block, your app will no longer request permission until the user manually changes the permission status and “unblocks” your app. This option is hidden in the Settings panel.

Use PushManager to subscribe to users

Once we have our Service Worker registered and we’ve got permission, we can subscribe a user by calling registration.pushManager.subscribe() when you register your Service Worker. Once we register the Service Worker, has obtained the permission, can be registered in the server thread called when registration. PushManager. The subscribe () subscribers

This code (including registration of service worker threads) :

function subscribeUserToPush() {
  return navigator.serviceWorker.register('service-worker.js')
  .then(function(registration) {
    var subscribeOptions = {
      userVisibleOnly: true,
      applicationServerKey: btoa(
        'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U'
      )
    };

    return registration.pushManager.subscribe(subscribeOptions);
  })
  .then(function(pushSubscription) {
    console.log('PushSubscription: ', JSON.stringify(pushSubscription));
    return pushSubscription;
  });
}
Copy the code

Registration. PushManager. Subscribe (options) to an options object, object contains optional and necessary properties

  • UserVisibleOnly: a Boolean value indicating that the returned push subscription will only be used for messages that are visible to the user. For example, true, otherwise an exception will occur. (Historical reasons)
  • applicationServerKey: a Base64 encodingDOMStringorArrayBufferContains a public key that authenticates the push service of the application service.

Your server will need to generate a pair of application service keys — these are the VAPID secret keys, which are unique to the server. They are a pair and contain public and private keys. The private key is stored on the push server, and the public key is used to exchange data with the client. Keys allow a push service to know which application service subscribing to the user and ensure that the same application server is pushing messages to the specified user.

You only need to create a key for your application once.

When subscribing to a user, the browser passes the applicationServerKey to the push service, so the push service can bind your public key to the user’s PushSubscription to see what happens:

  • The application loads and then callssubscribe()To pass the service public key
  • The browser makes a request to the push service, generates an endpoint combined with the key, and returns the endpoint to the browser
  • The browser adds this endpoint tosubscribe()The returnedPushSubscriptionobject

Then, whenever you want to send a push message, you need to create an authentication header that contains the signature information, which contains the server private key. When the push service receives a request to send a message, it queries the public key to verify the header information – the public key is connected to the endpoint in the second step

PushSubscription object

PushSubscription contains all the information needed to send push messages to the user’s device. It looks like this

{
    "endpoint": "https://domain.pushservice.com/some-id",\
        "keys": {                              "p256dh":"BIPUL12DLfytvTajnryr3PJdAgXS3HGMlLqndGcJGabyhHheJYlNGCeXl1dn18gSJ1WArAPIxr4gK0_dQds4yiI=",\
        "auth":"FPssMOQPmLmXWmdSTdbKVw=="\
    }
} 
Copy the code

The endpoint is the URL of the push service. To push the message, send a POST request to the URL

The keys object contains the values used to encrypt the data that is sent with the push message

Once the user has been subscribed, PushSubscription needs to be sent to the server. On the server, you can store subscription data in the database, and now you can send push messages to users

Sending push Messages

If you want to send push messages to your users, the first thing you need is a push service. You tell the server everything about what data to send, who to send the message to, and how to send the message. Typically, these interface calls are made by the message push server.

Push service

The message push service is used to receive the message push request, validate the request, and push the message to the appropriate browser side.

Note that the push service is not managed by you, it is a third party service. Your service communicates with the push service through an API. Look at Google’s FCM as an example of a push service.

The push service takes care of all the hassles. For example, if the browser is offline, before sending messages, the push service will queue messages to hang until the browser is back online

Every browser can use any push service, but that’s out of the developer’s control.

However, all push services have the same API, which makes it less painful to implement.

To get the URL for the request to process the push message, you need to check the endpoint stored in the PushSubscription object.

Push Service API

The Push Service API provides a way to send messages to users. This API is called the Web Push Protocol, and it is defined according to the IEFT specification, which defines how to invoke the Push API. When you send push messages, make sure you encrypt them. This prevents the push service from seeing the sent data. This is important because the browser decides which push service to use (which may use untrusted and insecure push services)

The descriptions of push messages are as follows:

  • TTL – Determines how long a message needs to be queued before it can be deleted or distributed.
  • Priority – Defines the Priority of each message. The push service will send a high priority message in order to protect the user’s battery life
  • Topic – Defines a Topic name for push messages, and new messages replace the same Topic name in pending messages, so that users do not receive expired messages once the device is activated.

The browser push event

Once we have sent the message to the push server as described above, the message will remain in a suspended state until the following happens

  • Equipment online
  • According to TTL, the message in the queue is expired

When the push service distributes a message, the browser will receive it, decrypt it, and then distribute a push event in the service worker

The cool thing about this is that even if your page is not open, the browser can still execute your ServiceWorker. The following happens:

  • Push service to the browser, the browser decrypts
  • The browser wakes up the Service Worker
  • The triggerpushEvent to the Service Worker

Listening for push events is very similar to listening for other events written in JavaScript

self.addEventListener('push', function(event) { var promise = self.registration.showNotification('Push notification! '); event.waitUntil(promise); });Copy the code

One thing to understand about Service Workers is that their runtime cannot be controlled manually. Only the browser can wake it up and end it.

In Service Workers, event.Waituntil (Promise) tells the browser to keep working until the promise is complete. If you want to complete Service Workers, the browser should not terminate it. Consider an example of handling a push event:

self.addEventListener('push', function(event) { var promise = self.registration.showNotification('Push notification! '); event.waitUntil(promise); });Copy the code

Call self. Registration. ShowNotification popup a notification to the user () and returns a promise, once the notification show complete parsing is complete.

You can visually set up the showNotification(title, options) method to match your requirements. The title argument is a string and options is an object like this:

{\
"//": "Visual Options",\
"body": "<String>",\
"icon": "<URL String>",\
"image": "<URL String>",\
"badge": "<URL String>",\
"vibrate": "<Array of Integers>",\
"sound": "<URL String>",\
"dir": "<String of 'auto' | 'ltr' | 'rtl'>",\
\
"//": "Behavioural Options",\
"tag": "<String>",\
"data": "<Anything>",\
"requireInteraction": "<boolean>",\
"renotify": "<Boolean>",\
"silent": "<Boolean>",\
\
"//": "Both Visual & Behavioural Options",\
"actions": "<Array of Strings>",\
\
"//": "Information Option. No visual affect.",\
"timestamp": "<Long>"\
}
Copy the code

For more details – developer.mozilla.org/en-US/docs/… .

Push notifications are a great way to get users’ attention when there’s important, urgent, real-time information that needs to be shared,