javascript - 如何通过 Node.js 上的推送通知实现一些复杂的行为
问题描述
我正在试验从 Node.js 应用程序发送的推送通知。遵循一些教程和示例,我现在有了一个可以开始工作的迷你应用程序。
它所做的非常基本,当它被加载到浏览器中时,会触发一个通知,并且用户会看到一条消息弹出。
它基本上由四个文件组成:index.js、index.html、worker.js 和 client.js。
作为第一个实验,我想实现一些稍微复杂的行为。
应用程序应在启动时触发 A 类型的通知(正如它已经在做的那样),然后每 121 分钟触发 B 类型的通知。
这种事情是可能的还是不可能的?
如果有可能,我该怎么做?
作为参考,我在这里放了两个相关文件:
index.js:
const express = require('express'),
webPush = require('web-push'),
bodyParser = require('body-parser'),
path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'client')));
app.use(bodyParser.json());
const privateVapIdKey = process.env.privVapIdKey,
publicVapIdKey = process.env.pubVapIdKey;
webPush.setVapidDetails(
'mailto:myemail@example.com',
publicVapIdKey,privateVapIdKey);
// Subscribe Route.
app.post('/subscribe',(req,res) => {
const subscription = req.body; // Get Push Subscription Object.
res.status(201).json({}); // Send 201. Resource created.
// Do a lot of useful things ......
.......
// Create the PayLoad.
const payload = JSON.stringify({
title:'A big title!',
........
});
// Pass Object to sendNotification.
webPush.sendNotification(subscription,payload).catch(err => console.error(err));
});
const port = 5003;
const PORT = process.env.PORT || port;
app.listen(PORT, () => console.log(`Listening on ${ PORT }`));
客户端.js:
const publicVapIdKey = 'my-secret-3453754...pubVapIdKey';
// Chec for ServiceWorker.
if ('serviceWorker' in navigator) {
send().catch(err => console.error(err));
}
// Register ServiceWorker, Register Push, Send Push.
async function send() {
console.log("Registering ServiceWorker.");
const register = await navigator.serviceWorker.register('/worker.js', {
scope: "/"
});
console.log('ServiceWorker registered.');
console.log("Registering Push.");
//register.pushManager.uns
const subscription = await register.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(publicVapIdKey)
});
console.log('Push registered.');
console.log("Sending Push.");
await fetch('/subscribe', {
method: 'POST',
body: JSON.stringify(subscription),
headers: {
'content-type': 'application/json'
}
});
console.log('Push sent.');
}
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;
}
解决方案
这是可能的!但我建议您将Admin FCM用于服务器端,它比web-push更新的库和更容易推送通知的方式。
//node.js serverside code
const FCM = require("firebase-admin");
//fcm-push-notification.json is where all the configurations are
const serviceAccount = require("fcm-push-notification.json");
FCM.initializeApp({
credential: SERVICE_ACCOUNT,
databaseURL: DBURL
});
// In your Subscribe Route.
app.post('/subscribe',(req,res) => {
FCM.messaging()
.sendToDevice(
DEVICE_TOKEN,
{
data: DATA,
notification: {
title: "A big title!",
body: "HELLO PUSH!"
}
}
)
.then(res => {
// do something here
})
});
这是服务人员
// put firebase-messaging-sw.js service worker
// this is to get notified in the background when the tab is closed on not active
(global => {
importScripts("https://www.gstatic.com/firebasejs/4.8.1/firebase-app.js");
importScripts(
"https://www.gstatic.com/firebasejs/4.8.1/firebase-messaging.js"
);
firebase.initializeApp({
messagingSenderId: SENDER_ID
});
const messaging = firebase.messaging();
console.log("Service Worker started!");
messaging.setBackgroundMessageHandler(payload => {
console.log("Message received In background");
// Customize notification here
const notificationOptions = {
body: "Background Message body.",
icon: "/firebase-logo.png"
};
return global.registration.showNotification("TITLE", notificationOptions);
});
})(self);
在你的 javascript
//to get notified in forground just do this
import firebase from "firebase";
firebase.initializeApp(FCM_CONF);
let messaging = firebase.messaging();
messaging.usePublicVapidKey(VAPID_KEY);
messaging.onMessage(payload => {
console.log("Message received from foreground ");
});
最后创建一个 manifest.json
//create manifest.json with content like this
{
"gcm_sender_id": SENDER_ID
}
并且每 121 分钟触发一次 B 类通知。使用类似later.js 的东西
var later = require('later');
var schedule = later.parse.text('every 121 min');
var timer = later.setTimeout(() => {
// fired every 121 minutes
FCM.messaging()
.sendToDevice(
DEVICE_TOKEN,
{
data: DATA,
notification: {
title: "A big title!",
body: "HELLO PUSH!"
}
}
)
}, schedule);
推荐阅读
- java - JHipster - import-jdl - 字段已将 jhi_ 添加到名称
- html - 具有部分不透明灰色背景的对话窗口
- tla+ - TLC 无法处理规范的这种结合
- zip - 提取从 maven 程序集插件创建的 zip 文件时出错
- python - 具有分组功能的字符串模式聚合
- javascript - 用户开始输入时隐藏数据列表选项
- excel - 如何将两个具有不同触发器的子与工作表上的 Private Sub Worksheet_Change 合并
- amazon-web-services - 如何使 aws sagemaker 中的这个 IAM 角色错误消失?
- opencv - 错误:(-215:断言失败)totalSampleCount > 0 in function 'GMM::endLearning'
- mysql - MySQL 使用带有 IN 子查询的 CASE WHEN