消息侦听器和获取侦听器之间的 Service Worker 竞争条件

问题描述 投票:0回答:1

我的服务工作人员有一个变量来存储安全哈希,并将其注入到相关 HTTP 请求的标头中,然后服务器应用程序将与它自己的进行比较以使其成为安全登录。
哈希值是在后面动态生成的(在我的例子中使用 c# dotnet 在浏览器类中)。

以前我总是在从浏览器加载的页面上调用 postmessage 将哈希值更新到 sw 中。但遇到了一个问题,在 5-6 分钟不活动(未打开 devtools)的情况下,一旦单击页面上的按钮,sw 就会重新初始化或以空哈希值唤醒,从而以空值响应并验证失败。
所以我从 sw 添加了一个触发器,但随后遇到了消息侦听器和获取侦听器之间的竞争条件。我需要消息侦听器来更新 sw 中的哈希值,但同时获取侦听器重新定位。看来超时延迟不起作用。

console.log('top root log');

if (!self.secureHeader) {
    self.secureHeader = 'Empty';
    console.log('Refreshing header');

    // this is my trigger when sw re-init
    postMessage({ type: 'refreshHeader', msg: '' }, '*');

    //// this is a bad attempt which didn't block the listener
    // setTimeout(function() {
    //     console.log('timeout ended');
    // }, 50);
}
self.addEventListener('message', function (event) {
    if (event.data.type == 'setHeader') {
        self.secureHeader = event.data.msg;
        console.log('Header received:'+ self.secureHeader);
    } 
}, false);

self.addEventListener('fetch', function(e) {
    console.log(Responding: ${self.secureHeader});

    ////I tried timeout here, error: The event handler is already finished.
    //if (self.secureHeader === 'Empty')
    //timeout to do respond

    e.respondWith(
        fetch(request, {
        headers: getSecureHeaders(request)
    })
    .catch(() => {
        return caches.match(request);
    })
    );
});

根据我的测试,经过几分钟的等待和 sw 到期,
日志似乎是: (sw 唤醒)顶部根日志出现。
触发“刷新标题”。
获取事件开始。
然后“已收到标头”和“正在响应...”同时出现,
我怎样才能正确地链接它们?任何建议,谢谢。

javascript service-worker race-condition service-worker-events
1个回答
0
投票

创建超时不会停止获取事件处理程序。在提出

fetch()
请求之前,您需要一个可以等待的承诺。您可以在请求刷新的标头时初始化该承诺:

// runs when sw (re-)init
self.secureHeaderPromise = new Promise(resolve => {
    console.log('Refreshing header');

    postMessage({ type: 'refreshHeader', msg: '' }, '*');

    self.setSecureHeader = (value) => {
        console.log('First header received: '+value);
        resolve(value);
 
        // allow later updates
        self.setSecureHeader = (value) => {
            console.log('Header received :'+value);
            self.secureHeaderPromise = Promise.resolve(value);
        };
    };
});
self.addEventListener('message', function (event) {
    if (event.data.type == 'setHeader') {
        self.setSecureHeader(event.data.msg);
    } 
}, false);

self.addEventListener('fetch', function(e) {
    console.log(`Got request: ${e}`);
    e.respondWith(
        self.secureHeaderPromise.then(secureHeader => {
            console.log(`Responding: ${secureHeader}`);
            return fetch(request, {
                headers: getSecureHeaders(request)
            })
        }).catch(() => {
            return caches.match(request);
        })
    );
});
© www.soinside.com 2019 - 2024. All rights reserved.