导读:本期聚焦于小伙伴创作的《JavaScript推送通知如何实现?Web Push协议核心原理与实战详解》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《JavaScript推送通知如何实现?Web Push协议核心原理与实战详解》有用,将其分享出去将是对创作者最好的鼓励。

Web Push协议是一套允许服务端向浏览器推送消息的标准化协议,结合JavaScript和Service Worker能力,可实现网站在用户未活跃访问时也能发送通知,广泛应用于消息提醒、活动通知等场景。

JavaScript推送通知如何实现?Web Push协议核心原理与实战详解

Web Push协议核心架构

Web Push协议的整体流程分为三个核心环节,分别是前端订阅、服务端推送、浏览器接收处理,三者通过标准化的接口和加密规则实现安全通信。

核心参与角色

  • 浏览器:负责执行Service Worker脚本,接收推送消息并展示通知
  • 前端页面:通过JavaScript调用浏览器API生成推送订阅信息
  • 推送服务端:存储订阅信息,按照协议规范加密并发送推送消息
  • 推送服务:由浏览器厂商提供的中间服务,负责将服务端的消息转发给对应浏览器

协议核心特性

  • 基于HTTPS传输,保障通信安全
  • 消息内容需要加密,避免中间环节泄露
  • 支持离线推送,用户关闭页面也能接收消息

前端订阅推送的实现步骤

前端需要先注册Service Worker,再申请通知权限,最后生成推送订阅信息并发送给服务端存储。

1. 注册Service Worker

Service Worker是推送通知的接收载体,需要在页面加载时完成注册。

// 检查浏览器是否支持Service Worker
if ('serviceWorker' in navigator && 'PushManager' in window) {
  // 注册Service Worker文件
  navigator.serviceWorker.register('/sw.js')
    .then(registration => {
      console.log('Service Worker注册成功', registration);
      // 注册成功后申请推送订阅
      return registration.pushManager.subscribe({
        userVisibleOnly: true, // 推送消息必须显示通知
        applicationServerKey: urlBase64ToUint8Array('你的VAPID公钥') // VAPID公钥转换后的数组
      });
    })
    .then(subscription => {
      // 将订阅信息发送到服务端存储
      fetch('/save-subscription', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(subscription)
      });
    })
    .catch(err => {
      console.error('推送订阅失败', err);
    });
}

// VAPID公钥转换工具函数
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;
}

2. Service Worker接收推送消息

Service Worker脚本需要监听push事件,接收到消息后展示通知。

// sw.js 文件内容
self.addEventListener('push', event => {
  const data = event.data.json(); // 解析推送的消息内容
  const options = {
    body: data.body,
    icon: data.icon || '/default-icon.png',
    badge: data.badge || '/default-badge.png',
    data: {
      url: data.url || '/' // 点击通知跳转的地址
    }
  };
  // 展示通知
  event.waitUntil(
    self.registration.showNotification(data.title, options)
  );
});

// 监听通知点击事件
self.addEventListener('notificationclick', event => {
  event.notification.close();
  // 打开对应的页面
  event.waitUntil(
    clients.openWindow(event.notification.data.url)
  );
});

服务端推送消息的实现

服务端需要存储前端的订阅信息,按照Web Push协议规范加密消息,再调用推送服务接口发送消息。

1. 存储订阅信息

服务端接收到前端发送的订阅信息后,需要持久化存储,后续推送时根据订阅信息发送消息。订阅信息包含以下核心字段:

字段名说明
endpoint推送服务的地址,不同浏览器的推送服务地址不同
keys.p256dh浏览器生成的公钥,用于消息加密
keys.auth认证密钥,用于验证消息合法性

2. 消息加密与推送

Web Push协议要求消息必须经过加密,常用的Node.js实现示例如下:

const webpush = require('web-push');
const express = require('express');
const app = express();
app.use(express.json());

// 配置VAPID密钥,需要提前生成
const vapidKeys = {
  publicKey: '你的VAPID公钥',
  privateKey: '你的VAPID私钥'
};
webpush.setVapidDetails(
  'mailto:admin@ipipp.com', // 联系邮箱
  vapidKeys.publicKey,
  vapidKeys.privateKey
);

// 存储订阅信息的数组,实际项目中使用数据库存储
let subscriptions = [];

// 接收前端发送的订阅信息
app.post('/save-subscription', (req, res) => {
  subscriptions.push(req.body);
  res.json({ success: true });
});

// 推送消息接口
app.post('/send-notification', (req, res) => {
  const { title, body, url } = req.body;
  const payload = JSON.stringify({
    title,
    body,
    url
  });
  // 遍历所有订阅信息发送推送
  const promises = subscriptions.map(subscription => {
    return webpush.sendNotification(subscription, payload)
      .catch(err => {
        console.error('推送失败', err);
        // 如果订阅失效,从存储中移除
        if (err.statusCode === 410) {
          subscriptions = subscriptions.filter(sub => sub.endpoint !== subscription.endpoint);
        }
      });
  });
  Promise.all(promises).then(() => {
    res.json({ success: true });
  });
});

app.listen(3000, () => {
  console.log('服务端运行在3000端口');
});

常见问题与解决方案

  • 通知权限被拒绝:需要在用户操作触发时申请权限,不要页面加载就直接申请,提升用户接受度
  • 消息推送失败:检查VAPID密钥是否正确,消息是否按照规范加密,订阅信息是否完整
  • 离线无法接收:确保Service Worker注册成功,且订阅时userVisibleOnly参数设置为true
注意:不同浏览器的推送服务存在差异,测试时建议使用Chrome、Firefox等主流浏览器,且必须在HTTPS环境下运行,本地开发可以使用localhost绕过HTTPS限制。

JavaScriptWeb_Push推送通知Service_Worker修改时间:2026-07-24 06:18:32

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。