在客户端和serviceWorker之间传输数据

时间:2018-08-07 13:50:40

标签: javascript service-worker

我想尝试在serviceWorker中运行websockets。

我为注册serviceWorker编写代码:

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register(
            GetDataForUser.settings.service_worker + "?version=" + GetDataForUser.settings.service_worker_version,
            {scope: './'}
        )
        .then(() => navigator.serviceWorker
            .ready
            .then((worker) => {
        console.log(worker);
                worker.sync.register('syncdata');
            })
        )
        .catch((err) => console.log(err));
    navigator.serviceWorker.addEventListener('message', event => {
        console.log('++++++++++++++++++++', event.data.msg, event.data.url);
    });
}

并编写serviceWorker代码:

var ws = null;

self.addEventListener('install', (event) => {
    console.log('Install');
});

self.addEventListener('activate', (event) => {
    console.log('Activate');

    ws = new WebSocket('ws://local.ll:8880');

    ws.onopen = function() {
        console.log("Open");
    };

    // On message receive
    ws.onmessage = function (event) {
        console.log("Message receive " + event.data);
        console.log(event);
        event.ports[0].postMessage({'test': 'This is my response.'});
    };

    // On error connection
    ws.onerror = function (error) {
        console.log("Error " + error.message);
    };

    // On close connection
    ws.onclose = function (event) {
        if (event.wasClean) {
            console.log('clean closed');

        } else {
            console.log('broken connection');
        }
        console.log('Code: ' + event.code + ' reason: ' + event.reason);
    };
});

self.addEventListener('fetch', (event) => {});

self.addEventListener('message', function (evt) {
    console.log('postMessage received', evt.data);
    ws.send('121212');
});

我接下来尝试将数据发送到serviceWorker:

navigator.serviceWorker.controller.postMessage({'hello': 'world'});

但收到错误:

Uncaught TypeError: Cannot read property 'postMessage' of null

console.log(navigator.serviceWorker);
ServiceWorkerContainer {controller: null, ready: Promise, oncontrollerchange: null, onmessage: null}

尝试将消息从serviceWorker发送到下一个客户端:

event.ports[0].postMessage({'test': 'This is my response.'});

但是event.ports为空。

怎么了? 如何在客户端和serviceWorker之间传输数据。

2 个答案:

答案 0 :(得分:1)

要解决控制器为null的错误,您需要添加Activate事件监听器

self.clients.claim()

否则,激活服务工作者后,页面将不受下一次导航的控制。这样一来,服务人员就可以在页面处于活动状态时立即对其进行控制。

但是我不认为这是您唯一的问题。查看您的代码,我认为您在混淆WebSocket和MessageChannel。您似乎试图使用WebSocket在客户端和服务工作者之间发送消息,而您应该为此使用MessageChannel。

例如,如果我们想从客户端向SW发送消息并允许SW响应这些消息,则创建一个MessageChannel,然后发送该通道的端口以及消息供SW使用。他的回应。 在客户端中:

var msg = new MessageChannel();
msg.port1.onmessage = function(event){
    //Response received from SW
    console.log(event.data);
};
// Send message to SW
navigator.serviceWorker.controller.postMessage("hello", [msg_chan.port2]);

在SW中:

self.addEventListener('message', function(event){
    //Message received from client
    console.log(event.data);
    //Send response to client using the port that was sent with the message
    event.ports[0].postMessage("world");
});

答案 1 :(得分:0)

正确而有效的示例,仅用于理解,而非用于生产: https://github.com/Shkarbatov/WebSocketInServiceWorkerJS