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

如何解决Laravel项目中navigator.serviceWorker.ready执行停滞问题?

问题描述

Laravel项目集成通知系统并使用Service Worker,本地运行一切正常,但部署到服务器后功能失效。Service Worker已成功注册并正常运行,但代码执行到console.log('test')语句后便停滞,navigator.serviceWorker.ready相关逻辑无法推进。相关代码如下:

<script>
// Request permission for notifications
Notification.requestPermission(function(permission) {
    if (permission === "granted") {
        console.log("Notification permission granted!");
    } else {
        console.log("Notification permission denied or not defined!");
    }
});

// Register the service worker
navigator.serviceWorker.register("{{ URL::asset('public/service-worker.js') }}").then(function(registration) {
    console.log('Service worker registered successfully:', registration);
}).catch(function(error) {
    console.error('Error registering service worker:', error);
});

// Check if the 'enable' key already exists in local storage
if (localStorage.getItem('enable')) {
    // If it exists, hide the button
    document.getElementById('enable').style.display = 'none';
} else {
    // If it doesn't exist, add event listener to the button
    document.getElementById('enable').addEventListener('click', () => {
        askForPermission();
        localStorage.setItem('enable', 'true');
        document.getElementById('enable').style.display = 'none';
    });
}

// Function to ask for notification permission
function askForPermission() {
    Notification.requestPermission().then((permission) => {
        if (permission === 'granted') {
            // When permission is granted, register the service worker
            registerServiceWorker();
        } else {
            console.log("Notification permission denied!");
        }
    }).catch(function(error) {
        console.error('Error requesting notification permission:', error);
    });
}

// Function to register the service worker
function registerServiceWorker() {
    console.log('test');
    navigator.serviceWorker.ready.then((sw) => {
        sw.pushManager.subscribe({
            userVisibleOnly: true,
            applicationServerKey: "BFSaQyz3LSete1tR6WhZFXbvC2WfWRXDfeqA0j7sm2GesTOoruXKh9QMWC1XRsG25L4ZTqhjze0HnhIGEpKsIs8"
        }).then((subscription) => {
            console.log('Subscription successful:', subscription);
            saveSub(JSON.stringify(subscription));
        }).catch(function(error) {
            console.error('Error subscribing to push notifications:', error);
        });
    }).catch(function(error) {
        console.error('Error retrieving service worker:', error);
    });
}

// Function to save the subscription on the server
function saveSub(sub) {
    $.ajax({
        type: 'post',
        url: '{{ URL('save-push-notification-sub') }}',
        data: {
            '_token': "{{ csrf_token() }}",
            'sub': sub,
        },
        success: function(data) {
            console.log('Subscription saved on server successfully:', data);
        },
        error: function(error) {
            console.error('Error saving subscription on server:', error);
        }
    });
}
</script>
排查与解决方案

以下是针对部署后Service Worker ready状态无法触发的常见问题及解决办法:

  • HTTPS环境检查
    Service Worker的ready状态及Push API仅支持HTTPS环境(localhost除外)。确认服务器已配置有效SSL证书,网站通过HTTPS协议访问。

  • 修正Service Worker路径
    原代码中URL::asset('public/service-worker.js')存在路径冗余,Laravel的asset()方法默认指向public目录,应改为{{ asset('service-worker.js') }}。同时确认服务器public目录下确实存在该文件。

  • 调整Service Worker作用域
    Service Worker的默认作用域是其所在目录,若文件不在网站根目录,可能导致ready状态无法触发。建议将service-worker.js放在public根目录下,确保注册路径为根路径。

  • 优化ready状态监听逻辑
    直接调用navigator.serviceWorker.ready可能因Service Worker未完全激活而停滞,可修改为先获取已注册实例再监听ready状态:

    function registerServiceWorker() {
        console.log('test');
        navigator.serviceWorker.getRegistration().then(registration => {
            if (registration) {
                registration.ready.then((sw) => {
                    sw.pushManager.subscribe({
                        userVisibleOnly: true,
                        applicationServerKey: urlBase64ToUint8Array("BFSaQyz3LSete1tR6WhZFXbvC2WfWRXDfeqA0j7sm2GesTOoruXKh9QMWC1XRsG25L4ZTqhjze0HnhIGEpKsIs8")
                    }).then((subscription) => {
                        console.log('Subscription successful:', subscription);
                        saveSub(JSON.stringify(subscription));
                    }).catch(function(error) {
                        console.error('Error subscribing to push notifications:', error);
                    });
                }).catch(function(error) {
                    console.error('Error retrieving service worker ready state:', error);
                });
            } else {
                console.error('No service worker registration found');
            }
        }).catch(err => console.error('Failed to get registration:', err));
    }
    
  • 修复Application Server Key格式
    Push API要求applicationServerKey为Uint8Array格式,需添加转换函数:

    function urlBase64ToUint8Array(base64String) {
        const padding = '='.repeat((4 - base64String.length % 4) % 4);
        const base64 = (base64String + padding)
            .replace(/-/g, '+')
            .replace(/_/g, '/');
        const rawData = window.atob(base64);
        return Uint8Array.from([...rawData].map(char => char.charCodeAt(0)));
    }
    

    调用时将原字符串替换为urlBase64ToUint8Array("你的密钥字符串")。

  • 清除浏览器缓存
    服务器可能缓存了旧版Service Worker文件,导致新代码无法生效。可在文件名后添加版本号(如service-worker-v1.js),或配置服务器禁止缓存Service Worker文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 19:02:03