问题描述
我愿意在我的网络应用上使用网络推送通知。我已经在前端(React)上设置了 serviceWorkers,并在我的后端(NodeJS)上实现了网络推送通知。现在我只需要发送特定于用户的通知,这意味着只有特定用户才能收到这些通知。
例如在我的网络应用程序的后端,我将收到一些实时值。说,有一个名为的集合 “用户”将存储所有用户的数据。现在,这些用户将拥有一个名为“设备”的字段,用户将在该字段中收到将在 40-50 秒内更新的数值。
现在,它们将成为这些值的阈值。说,例如如果该值达到 200 以上,则该特定用户应收到推送通知,让他们知道设备已达到限制。
我如何才能创建此类特定于用户的推送通知,其中通知将仅发送给设备价值已达到 200 以上的用户? P.S 我使用 Mongoose 作为数据库。
前端代码(react.js)
sw.js:
self.addEventListener("notificationclick",function (event) {
// on Notification click
let notification = event.notification;
let action = event.action;
console.log("Notification====>",notification);
if (action === "confirm") {
console.log("Confirm clicked");
notification.close(); // Closes the notifcation
} else {
event.waitUntil(
clients.matchAll().then(function (clis) {
var client = clis.find(function (c) {
return c.visibilityState === "visible";
});
if (client !== undefined) {
// found open window
client.navigate("http://localhost:3000"); // means website opens on the same tab where user is on
client.focus();
} else {
// if client's window was not open
clients.openWindow("http://localhost:3000"); // when browser window is closed,open website
}
notification.close();
})
);
console.log(action); // name of action,basically id
}
});
self.addEventListener("notificationclose",function (event) {
console.log("Notification closed",event);
});
// triggers when we get an incoming push message
self.addEventListener("push",function (event) {
console.log("Push notifications recieved from eventListner",event);
var data = { title: "New!",content: "New things" };
if (event.data) {
// check if payload exists(from backend)
data = JSON.parse(event.data.text()); // recieve payload & store
}
var options = {
body: data.content,icon: "https://iconarchive.com/download/i90141/icons8/windows-8/Cinema-Avengers.ico",tag: "id1",renotify: true,};
event.waitUntil(self.registration.showNotification(data.title,options));
});
swReg.js:
if ("serviceWorker" in navigator) {
console.log("Registering service worker");
navigator.serviceWorker
.register("/sw.js")
.then(() => {
console.log("Service Worker has been registered");
})
.catch((err) => console.error(err));
}
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;
}
function displayConfirmNotification() {
if ("serviceWorker" in navigator) {
const options = {
body: "After subscription managing done",// icon: "/src/assets/img/pattern_react.png",// tag:"" ==> in advanced options.
vibrate: [100,50,200],// badge:""
tag: "confirm",actions: [
{ action: "confirm",title: "okay" },// optnl icon:""
{ action: "cancel",title: "cancel" },],};
navigator.serviceWorker.ready.then(function (swreg) {
swreg.showNotification("Successfully subscribed sW",options);
});
}
}
function configPushSub() {
if (!("serviceWorker" in navigator)) {
return;
}
var reg;
navigator.serviceWorker.ready
.then(function (swreg) {
// access to sW registration
reg = swreg;
return swreg.pushManager.getSubscription(); // returns any existing subscription
})
.then(function (sub) {
// sub holds the current subscription,if subscription doesn't exist then it returns null
if (sub === null) {
// Create a new subscription
var vapidPublicKey = KEY;
var convertedPublicKey = urlBase64ToUint8Array(vapidPublicKey);
return reg.pushManager.subscribe({
userVisibleOnly: true,// for security
applicationServerKey: convertedPublicKey,// for security & server storage
}); // create new subscription
} else {
// We already have a subscription
}
})
.then(function (newSub) {
// have to pass this subscription(new one) to backend
console.log("New subb =======>",newSub);
return fetch("http://localhost:8000/subscribetoPushNotifications",{
method: "POST",headers: {
"Content-Type": "application/json",Accept: "application/json",},body: JSON.stringify({
subscriptionObj: newSub,}),});
})
.then(function (res) {
if (res.ok) {
displayConfirmNotification();
}
})
.catch(function (e) {
console.log("err while subbing====>",e);
});
}
function askForNotificationPermission() {
Notification.requestPermission(function (result) {
console.log("User's choice",result);
if (result !== "granted") {
console.log("Permission rights not granted");
} else {
configPushSub();
// displayConfirmNotification();
}
});
}
if ("Notification" in window) {
askForNotificationPermission();
}
后端: 订阅 API:
exports.subscribetoPushNotifications = async (req,res) => {
const { subscriptionObj } = req.body;
// console.log("Subscription object=====>",subscriptionObj);
if (subscriptionObj != undefined || subscriptionObj != null) {
let newSubscription = new Subscription({
pushSubscription: subscriptionObj,});
await newSubscription.save();
if (newSubscription) {
console.log(newSubscription);
return res.status(200).send("Subscription made");
} else {
console.log("Not subbed");
return res.status(400).send("Subscription not made");
}
} else {
console.log("Sub obj is null");
return res.status(400).send("Sub obj was null");
}
};
检查值是否超过阈值,然后发送通知:(例如目的)。这是仅适用于单个用户的示例。
exports.checkStatus = async () => {
schedule.scheduleJob("*/10 * * * * *",async () => {
let subscriptions = await Subscription.find({});
let Email = "james@mail.com";
let findUser = await User.findOne({ Email });
if (findUser) {
if (findUser.device > 200) // findUser.device contains the value
{
for (let i = 0; i < subscriptions.length; i++) { //Notification will be sent to all users which I don't want.
webpush.sendNotification(
subscriptions[i].pushSubscription,JSON.stringify({
title: "Alert",content: "Value has reached it's limit",})
);
}
}
}
});
};
我如何才能使这项工作正常进行,以便只有设备价值超过 200 的用户才会收到通知,而不是所有订阅用户。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)