You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AngularJS集成Firebase Messaging遇messaging/only-available-in-sw错误求助

解决Firebase Messaging的messaging/only-available-in-sw错误&Service Worker入门

先解决你的核心错误

你碰到的这个报错原因很直接:setBackgroundMessageHandler这个方法只能在Service Worker脚本里调用,但你现在是把它放在普通网页脚本(configFcm.js,运行在浏览器主线程)里执行,所以Firebase直接抛出了权限错误。


什么是Service Worker?

简单来说,Service Worker是一种运行在浏览器后台的独立脚本,和你的网页主线程完全隔离:

  • 它仅在客户端(浏览器)运行,完全没有服务器端的参与;
  • 它没有DOM访问权限,不能直接操作页面元素;
  • 生命周期和网页无关——哪怕你关闭了所有网页标签,只要浏览器没退出,它可能还在后台运行;
  • 主要用来处理离线缓存、后台同步、推送通知这类不需要页面处于活跃状态也能工作的任务。

修正你的Firebase Messaging配置

按照Firebase的规范,我们需要把后台通知的逻辑放到单独的Service Worker文件里,前台通知的逻辑留在主线程脚本中:

1. 创建Service Worker文件(firebase-messaging-sw.js)

把原来configFcm.js里的setBackgroundMessageHandler代码移到这个文件里,注意要用importScripts引入Firebase脚本(Service Worker环境不支持<script>标签):

// 引入Firebase核心库和Messaging模块
importScripts('https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.10.0/firebase-messaging.js');

// 初始化Firebase
const firebaseConfig = {
  apiKey: "AIzaSyDAVuWKUL-aPoGasdEi-EMR7uFN1gtgk0s",
  authDomain: "testproject-d71.firebaseapp.com",
  databaseURL: "https://testproject-12d71.firebaseio.com",
  projectId: "testproject-12d71",
  storageBucket: "",
  messagingSenderId: "123128116401"
};

firebase.initializeApp(firebaseConfig);

// 处理后台通知(应用关闭/后台时触发)
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function(payload) {
  console.log('[firebase-messaging-sw.js] Received background message ', payload);
  const notificationTitle = 'Title';
  const notificationOptions = {
    body: 'body.',
    icon: '/firebase-logo.png'
  };
  return self.registration.showNotification(notificationTitle, notificationOptions);
});

2. 修改configFcm.js(主线程脚本)

在这个文件里注册Service Worker,关联到Firebase Messaging,同时处理前台通知(应用打开时收到的消息):

// 初始化Firebase(如果index.html里已经初始化过,这里可以省略)
const config = {
  apiKey: "AIzaSyDAVuWKUL-aPoGasdEi-EMR7uFN1gtgk0s",
  authDomain: "testproject-d71.firebaseapp.com",
  databaseURL: "https://testproject-12d71.firebaseio.com",
  projectId: "testproject-12d71",
  storageBucket: "",
  messagingSenderId: "123128116401"
};
firebase.initializeApp(config);

const messaging = firebase.messaging();

// 注册Service Worker并关联到Firebase Messaging
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/firebase-messaging-sw.js')
    .then(function(registration) {
      console.log('Service Worker registered successfully:', registration.scope);
      messaging.useServiceWorker(registration);

      // 处理前台通知(应用处于活跃状态时触发)
      messaging.onMessage(function(payload) {
        console.log('Received foreground message:', payload);
        // 这里可以用AngularJS的组件自定义应用内通知,比如弹窗
        // 举个简单例子:
        alert(`应用内通知:${payload.notification.body}`);
      });
    })
    .catch(function(err) {
      console.error('Service Worker registration failed:', err);
    });
}

3. 修正manifest.json的细节

注意Firebase要求gcm_sender_id必须是固定值"103953800507"(不是你自己的sender id),同时补充必要的配置:

{
  "name": "Test Project",
  "short_name": "Test",
  "start_url": "/",
  "display": "standalone",
  "gcm_sender_id": "103953800507",
  "icons": [
    {
      "src": "/firebase-logo.png",
      "sizes": "192x192",
      "type": "image/png"
    }
  ]
}

最后梳理一下逻辑

  • 后台通知:当应用处于关闭或后台状态时,推送消息由Service Worker接收并处理,展示系统级通知;
  • 前台通知:当应用处于活跃状态时,推送消息由主线程脚本接收,你可以自定义应用内的通知展示(比如AngularJS的弹窗、内置通知组件);
  • Service Worker全程只在客户端浏览器运行,和你的AngularJS应用主线程完全独立,不能直接操作DOM。

内容的提问来源于stack exchange,提问作者BT101

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 09:04:25