【问题标题】:Request modification with service worker fetch listener使用服务工作者获取侦听器请求修改
【发布时间】:2019-11-30 12:44:37
【问题描述】:

我正在尝试在来自应用程序的所有网络请求上添加自定义标头,并且我正在尝试通过服务工作者获取来执行此操作。 header的内容需要来自app(client),所以在响应任何事件之前我需要等待客户端的响应。 以下是我实现这一目标的尝试

这是我的获取监听器代码

function send_message_to_client(client, msg){
    return new Promise(function(resolve, reject){
        var msg_chan = new MessageChannel();

        msg_chan.port1.onmessage = function(event){
            if(event.data.error){
                reject(event.data.error);
            }else{
                resolve(event.data);
            }
        };

        client.postMessage("SW Says: '"+msg+"'", [msg_chan.port2]);
    });
}

self.addEventListener('fetch', function (event) {

    event.waitUntil(async function () {
        const client = await clients.get(event.clientId);
        send_message_to_client(client, "Pass Transaction Details")
            .then(function (m) {
                var req = new Request(event.request.url, {
                    method: event.request.method,
                    headers: event.request.headers,
                    mode: 'same-origin',
                    credentials: event.request.credentials,
                    redirect: 'manual'
                });

                var res_obj = JSON.parse(m);
                req.headers.append('MY_CUSTOM_HEADER', res_obj.hdr_val);
                return event.respondWith(fetch(req));

            })
            .catch(function (error) {
                console.log("Error after event.respondWith call");
                console.log(error);
            });

    }());
});

这就是我如何注册这个工人和它的消息监听器

navigator.serviceWorker.register('/my-sw.js', {scope: '/'})
    .then(function(reg) {
        navigator.serviceWorker.onmessage = function (e) {
            var msg_reply = {
                "message" : "Replying to SW request",
            };
            msg_reply.hdr_val = sessionStorage.getItem('__data_val');
            console.log("Replying with "+ JSON.stringify(msg_reply));
            e.ports[0].postMessage(JSON.stringify(msg_reply));

        };
    }).catch(function(error) {
    // registration failed
    console.log('Registration failed with ' + error);
});

但显然它拍摄了 2 个请求,1 个原始请求和 1 个带有修改标头的请求。

知道我做错了什么吗?我是 javascript 的新手,如果有一些愚蠢的错误,请原谅我。

从 service worker 调试控制台,我发现它在 event.respondWith() 调用之后就进入了 catch 块,所以可能有问题?

【问题讨论】:

    标签: javascript service-worker


    【解决方案1】:

    您必须在 fetch 处理程序中同步调用 FetchEvent.respondWith()。在您的代码中,您同步调用waitUntil(),但稍后调用respondWith()。通过在从 fetch 处理程序返回之前不调用 respondWith(),您是在告诉浏览器继续其正常的网络路径而不会被拦截。

    我想你想要这样的东西:

    self.addEventListener('fetch', function (event) {
        // call respondWith() here
        event.respondWith(async function () {
            const client = await clients.get(event.clientId);
            send_message_to_client(client, "Pass Transaction Details")
                .then(function (m) {
                    var req = new Request(event.request.url, {
                        method: event.request.method,
                        headers: event.request.headers,
                        mode: 'same-origin',
                        credentials: event.request.credentials,
                        redirect: 'manual'
                    });
    
                    var res_obj = JSON.parse(m);
                    req.headers.append('MY_CUSTOM_HEADER', res_obj.hdr_val);
                    // just return the response back to the respondWith() here
                    return fetch(req);
    
                })
                // You probably want to add a .catch() to return some reasonable fallback
                // response.
    

    【讨论】:

    • 正是我需要的。非常感谢。
    猜你喜欢
    • 2020-06-27
    • 2019-11-29
    • 1970-01-01
    • 2020-09-12
    • 2017-01-31
    • 2018-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多