为什么serviceworker会导致每一秒的jquery发布都立即停止?

Why does serviceworker cause every second jquery post to instantly stall out?

本文关键字:jquery 一秒 serviceworker 为什么      更新时间:2023-09-26

我在标题中所述的内容只发生在chrome浏览器中,就像在firefox中"('serviceWorker' in navigator)"总是为false和"console "一样。warn('此浏览器不支持Service workers .');"触发。

如果你清除浏览器或隐身运行,那么它最初工作,但当你注销第一次,然后重新登录问题开始。

网络日志

下面是我注册SW的代码:

function activateSW(){
    if('serviceWorker' in navigator){
        if(window.location.pathname != '/'){
            //register with API
            if(!navigator.serviceWorker.controller) navigator.serviceWorker.register('/service-worker', { scope: '/' });
            //once registration is complete
            navigator.serviceWorker.ready.then(function(serviceWorkerRegistration){
                //get subscription
                serviceWorkerRegistration.pushManager.getSubscription().then(function(subscription){
                    //enable the user to alter the subscription
                    $('.js-enable-sub-test').removeAttr("disabled");
                    //set it to allready subscribed if it is so
                    if(subscription){
                        $('.js-enable-sub-test').prop("checked", true);
                        $('.js-enable-sub-test').parent().addClass('checked');
                    }
                });
            });
        }   
    }else{  
        console.warn('Service workers aren''t supported in this browser.');  
    } 
}

'/service-worker'是一个被发送到index.php(通过.htaccess)的请求。它最终在这个函数中结束:

function serviceworkerJS($params){
    $hash = API::request('settings', 'getSWHash', '');
    if($hash != false){
        setcookie('SW_Hash', $hash, time() + (86400 * 365 * 10), "/");
        header('Content-type: text/javascript');
        echo "'use strict';
var hash = '".$hash."';";
        include(ROOT_PATH.'public/js/service-worker.js');
    }elseif(isset($_COOKIE['SW_Hash'])){
        header('Content-type: text/javascript');
        echo "'use strict';
var hash = '".$_COOKIE['SW_Hash']."';";
        include(ROOT_PATH.'public/js/service-worker.js');
    }else{
        header('HTTP/1.1 404 Not Found');
    }
}

Service-worker.js在chrome://serviceworker-internals/中是这样的:(对地址的几处引用已用星号代替)

'use strict';
var hash = 'bd8e78963deebf350f851fbf8cdc5080';
var *****_API_ENDPOINT = 'https://*********.***/';
//For displaying notifications
function showNotification(title, body, icon, data, id) {
    var notificationOptions = {
        body: body,
        icon: icon,
        tag: id,
        data: data
    };
    //possibly unnecessary
    if(self.registration.showNotification){
        return self.registration.showNotification(title, notificationOptions);
    }else{
        return new Notification(title, notificationOptions);
    }
}
//asks the server for messages and sends them for displaying.
function getMessages(event){
    //showNotification('debug', 'initial', '', '', 'debug1');
    //build question
    var FD = new FormData();
    FD.append('hash', hash);
    //ask start20 for the notifications
    event.waitUntil(
        fetch(*****_API_ENDPOINT + 'ajax-get-SW-notification/', {method: 'post', body: FD}).then(function(response){
            //something went wrong
            if (response.status !== 200){
                console.log('Error communicating with ******, code: ' + response.status);
                showNotification('debug', 'picnic', '', '', 'debug2');
                throw new Error();
            }
            //decode the response
            return response.json().then(function(data){
                var len = data.notifications.length;
//showNotification('debug', len, '', '', 'propertyName');
                //Display
                for(var i = 0; i < len -1; i++){
                    showNotification(data.notifications[i].title, 
                                    data.notifications[i].body, 
                                    data.notifications[i].imageurl, 
                                    data.notifications[i].linkurl,
                                    data.notifications[i].hash);
                }
                //the last one needs to be returned to complete the promise
                return showNotification(data.notifications[len -1].title, 
                                        data.notifications[len -1].body, 
                                        data.notifications[len -1].imageurl, 
                                        data.notifications[len -1].linkurl,
                                        data.notifications[len -1].hash);
            });
        })
    );
}
//when the user installs a new SW
/*self.addEventListener('activate', function(event){
    //getMessages(event);
    //event.preventDefault();
    event.waitUntil(return self.registration.showNotification('bicnic', { body: '*p' }));
});*/
//when the serviceworker gets a puch from the server
self.addEventListener('push', function(event){
    getMessages(event);
    event.preventDefault();
});
//get the link associated witht he message when a user clicks on it
self.addEventListener('notificationclick', function(event){
    //ask if the notification has any link associated with it
    var FD = new FormData();
    FD.append('hash', event.notification.tag);
    //get the link
    event.waitUntil(
        fetch(******_API_ENDPOINT + 'ajax-notification-has-link/', {method: 'post', body: FD}).then(function(response){
            //something went wrong
            if (response.status !== 200){
                console.log('Error communicating with ********, code: ' + response.status);
                return;
            }
            //decode the response
            return response.json().then(function(data){
                //if there's a link associated with the message hash
                if(data.link){
                    console.log(******_API_ENDPOINT + 'notification-link/' + event.notification.tag);
                    return clients.openWindow(*****_API_ENDPOINT + 'notification-link/' + event.notification.tag);
                }
            });
        })
    );
});

//unnecessary?
/*self.addEventListener('install', function(event){
    //event.preventDefault();
});
self.addEventListener("fetch", function(event) {
});//*/

现在如果你注释掉"if(!navigator.serviceWorker.controller) navigator.serviceWorker.controller "Register ('/service-worker', {scope: '/'});",那么问题就消失了,但是serviceworker的订阅和取消订阅会停止工作。(if语句似乎没有多大作用,只是为了解决这个问题而添加的)

我已经尝试了许多版本的activateSW(),不同的表达式运行的各种条件,并没有设法使一个版本的工作,而不破坏serviceworker。我也试着在各个点(注册,帖子)上捕捉错误,但这是不成功的,因为他们都没有抛出任何错误。

我怀疑问题可能是,当你注册serviceworker时,激活事件被触发。现在,如果您捕获了这个并完成了事件承诺,那么您将无法订阅。但是,我怀疑serviceworker在您注销时仍然处于活动状态,这会导致问题。

如果你有问题或想看更多的代码,请直接问。

编辑;下面是解决方案:

self.addEventListener("fetch", function(event) {
    event.respondWith(
        fetch(event.request)
    );
});

你所看到的是Chrome DevTools的网络面板中令人困惑的噪音,但不应该对你的应用程序的行为产生实际影响。

如果一个service worker控制一个页面,但不包括fetch事件处理程序,当前版本的Chrome (M44稳定版和M46金丝鼠版)最终会在(canceled)状态的网络面板中记录所有网络请求,就像你看到的那样。实际的请求仍然在没有service worker干预的情况下发出,这是第二个成功记录的条目。从您的页面的角度来看,事情应该像预期的那样工作,但我完全理解这种困惑。

我听说有计划使Chrome的service worker实现更像一个"no-op",当一个网络请求,没有fetch事件处理程序。我不知道这些计划进行得有多远,但我希望你看到的噪音一旦发生就会消失。