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
相关产品推荐
相关产品推荐

