簡體   English   中英

使用 NodeJs Express 在 JavaScript 上推送通知

[英]Push notifications on JavaScript with NodeJs Express

我想從 NodeJs 向特定用戶發送通知。 如果可能的話,這個想法是獨立於 firebase 和任何類型的第三方服務器。 我找到了很多關於如何構建服務工作者的信息和很多關於顯示通知的信息,但是我找不到任何對我有用的關於將推送消息發送給要顯示的工作人員的信息。

這是 service-worker.js

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/layout/service-worker.js')
    .then(function (registration) {
        registration.pushManager.subscribe({
            userVisibleOnly: true
        }).then(function (subscription) {
            isPushEnabled = true;
            console.log("subscription.endpoint: ", subscription.endpoint);
            //Here I will have to store the endpoint on my DB
        });
    }).catch(function (err) {
        console.log(err);
    });
}

//I think that this could be the listener, but I don't know how to trigger it from the server
this.onpush = function (event) {
    console.log(event.data);
}

我有顯示通知的代碼(當我可以發送通知時)

var notificationTitle = 'Title';
var notificationOptions = {
    "body": "Some text",
    //"icon": "images/icon.png",
    "vibrate": [200, 100, 200, 100, 200, 100, 400]
}
showNotification(notificationTitle, notificationOptions);

這個想法是在“onpush”事件中實現這個代碼,我會知道我會收到什么格式。

所以我需要一種方法來將推送發送到這些方法,但現在不知道如何去做。 我讀了一些關於帶有 VAPID 鍵的節點 web-push 模塊的內容,但我仍然沒有找到發送者噴氣機。 我有一個 manifest.json,我不知道它是否真的做任何事情(我讀到這是 Chrome 導航器所必需的,但不知道,我正在 Chrome、Firefox 和 Edge 中測試所有內容)。

此外,我在 localhost 中使用 http 對其進行測試。 我真的不知道如果沒有 SSL 證書或自動簽名證書,這是否可行。

每一次幫助都將不勝感激。

我找到了解決方案。 我不知道是否是最佳的,但它對我有用:

起初需要許多配置步驟:

//Installl web push module
npm install web-push --save

//Generate VAPID keys by console
cd ./node_modules/.bin/web-push generate-vapid-keys

//Store VAPID keys on environment
publicVapidKey: 'generated key',
privateVapidKey: 'generated key'
process.env.PUBLIC_VAPID_KEY = config.publicVapidKey;
process.env.PRIVATE_VAPID_KEY = config.privateVapidKey;

這是從客戶端接收訂閱並將其存儲在數據庫中的nodejs controller 代碼:

//Subscriptions
app.post('/subscribe', (req, res) => {
    const subscription = req.body.subscription;
    const userId = req.body.userId;
    console.dir(subscription);
    //TODO: Store subscription keys and userId in DB
    webpush.setVapidDetails(
        process.env.DOMAIN, 
        process.env.PUBLIC_VAPID_KEY, 
        process.env.PRIVATE_VAPID_KEY
    );
    res.sendStatus(200);
    const payload = JSON.stringify({
        title: model.lang.pushTitle,
        body: model.lang.pushBody
    });
    webpush.sendNotification(subscription, payload);
});

這是我發現將消息從服務器推送到客戶端或客戶端的方法:

//Send push message
//TODO: Recover subscription keys from DB
var subscription = { 
    endpoint: 'recover from DB',
    expirationTime: null,
    keys: { 
        p256dh: 'recover from DB',
        auth: 'recover from DB' 
    } 
};
const payload = JSON.stringify({
    title: 'Notification Title',
    body: 'Notification message'
});
webpush.setVapidDetails(
    process.env.DOMAIN, 
    process.env.PUBLIC_VAPID_KEY, 
    process.env.PRIVATE_VAPID_KEY
);
webpush.sendNotification(subscription, payload)
.catch(function(err) {
    console.log(err);
});

這里有客戶端視圖腳本中的方法可以使用必要的數據進行訂閱:

//Start subscription
const publicVapidKey = 'public key of server';
if (window.Notification) {
    if (Notification.permission != 'granted') {
        Notification.requestPermission(() => {
            if (Notification.permission === 'granted') {
                getSubscriptionObject().then(subscribe)
            }
        }).catch(function(err) {
            console.log(err);
        });
    }
}

//Generate subscription object
function getSubscriptionObject() {
    return navigator.serviceWorker.register('/layout/service-worker-push.js')
    .then((worker) => {
        return worker.pushManager.subscribe({
            userVisibleOnly: true,
            applicationServerKey: urlBase64ToUint8Array(publicVapidKey)
        }).catch(function(err) {
            console.log(err);
        });
    }).catch(function(err) {
        console.log(err);
    });
}

//Send subscription to server
function subscribe(subscription) {
    return fetch(window.location.origin + '/subscribe', {
        method: 'POST',
        body: JSON.stringify({
            subscription: subscription,
            userId: mv.user_id != undefined ? mv.user_id : ''
        }),
        headers: {
            'content-type': 'application/json'
        }
    }).catch(function(err) {
        console.log(err);
    });
}

//Decoder base64 to uint8
function urlBase64ToUint8Array(base64String) {
    const padding = '='.repeat((4 - base64String.length % 4) % 4);
    const base64 = (base64String + padding)
        .replace(/-/g, '+')
        .replace(/_/g, '/');
    const rawData = window.atob(base64);
    const outputArray = new Uint8Array(rawData.length);
    for (let i = 0; i < rawData.length; ++i) {
        outputArray[i] = rawData.charCodeAt(i);
    }
    return outputArray;
}

這是在客戶端中施展魔法的woker(必須在視圖中導入)

//Event that shows a notification when is received by push
self.addEventListener('push', event => {
    const data = event.data.json();
    self.registration.showNotification(data.title, {
      body: data.body,
      icon: "/layout/src/android-chrome-192x192.png"
    });
});

//Event on notification click (have problems almost in Chrome)
self.addEventListener('notificationclick', () => {
    console.log('Notificación pulsada!');
});

而且,考慮到工人的重要性

<script type="text/javascript" src="/layout/service-worker-push.js"></script>

注意:我只在 localhost 上測試過,所以我不知道是否需要 SSL 證書。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM