由网络工作者访问 [英] Access dom by web worker

查看:213
本文介绍了由网络工作者访问的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很疯狂,需要你的帮助。
我正在处理一个serviceworker项目,我正在处理一个javascript问题。我要主文件。 server.html文件,其中我调用第52行中的外部service-worker.js文件。
这是我的 server.html 文件

 < body> 
< div class =container>
< h1> PRESENTER< / h1>
< div id =nicky>昵称:< span id =昵称>< / span>< / div>
< form id =form-nickname =form-nickmethod =postaction =>
< div class =formelement>
< label name =labelnickfor =nick>昵称:< / label>
< input type =textid =nickname =nick>
< button type =submit> OK< / button>
< / div>
< / form>< br />< br />

< h1>>< / h1>< div id =talker>< / div>

< button type =buttonclass =button blueid =blue-displaydisabled>< / button>< br />

< button type =buttonclass =button reddisabled>< / button>< br />

< button type =buttonclass =button lightbluedisabled>< / button>
< / div> <! - container - >


< script type =text / javascript>
/ * ======================================== ================================= * /
$(document).ready(function( ){
console.log(jquery ready function);

$('#nick')。focus();

$('#form -nick')。submit(function(){
var form = $('#form-nick');
var data = form.serialize();
$ .post(' nicky.php',data,function(response){
if(response){
$('#nicky')。show();
$('#nickname' (回答);
$('#form-nick')hide();
$('。blue,.red,.lightblue')fadeIn(100);

if('serviceWorker'in navigator){
//注册服务工作者
navigator.serviceWorker.register('service-worker.js')然后(function(reg){
console.log(SW注册成功。范围是+ reg.scope;

})。catch(function(err){
console.error(SW registration failed with error+ err);
});
}
} else {

}
});
return false;
});
} );
< / script>
< / body>

这里是 service-worker.js 文件

  //安装
//安装Service Worker
self.addEventListener('install',function(event){
console.log('>> sw installed!');
});
/ / service Worker Active
self.addEventListener('activate',function(event){
console.log('>> sw activated!');
});
// Service Worker显示消息
self.addEventListener('message',functi on(event){
console.log(event.data);
send_message_to_all_clients(event.data);
document.getElementById(talker)。innerHTML = event.data;
});

在最后一行我想将接收到的消息插入divtalker。但是我总是得到错误 service-worker.js:17未捕获ReferenceError:文档未定义



I小心,加载文件加载js-File后。
现在我不知道我做错了什么
谢谢。

解决方案

服务工作者 —网络工作者一般 —根本没有直接访问DOM。相反,让工作者将信息发布到主线程,并且主线程中的代码适当地更新DOM。浏览器上的JavaScript的标题模型是只有一个主要的UI线程(您的页内代码运行的默认)线程,可以访问DOM。其他人被封闭了。



此页面此页面都谈论服务工作者和客户之间的信息。这是一个非常简单的例子:



页面中的脚本加载服务工作者:

 (function(){
use strict;

if(!navigator.serviceWorker ||!navigator.serviceWorker.register){
console.log 这个浏览器不支持服务工作者);
return;
}

//听服务工作者的消息
navigator.serviceWorker.addEventListener 'message',function(event){
console.log(Got service from service worker:+ event.data);
});

//我们被控制?
if(navigator.serviceWorker.controller){
//是,发送我们的控制器一条消息
console.log(发送hi到控制器);
navigator.serviceWorker.controller.postMessage(hi);
} else {
//否,注册一个服务工作者来控制像我们这样的页面
//注意它赢了不要控制这个这个页面的效果只有在$ *
//的范围内的
navigator.serviceWorker.register(service-worker.js)
.then(function(registration){
console.log(Service worker registered,scope:+ registration.scope );
console.log(刷新页面来谈论它);
//如果我们想要,我们可能会做location.reload();,以便我们将由
})
.catch(function(error){
console.log(Service worker registration failed:+ error.message);
});
}
})();

而在 service-worker.js

  self.addEventListener(message,function(event){
event.source.postMessage( + event.data);
});

这依赖于 event.source ,其中由当前版本的Chrome和Firefox支持。



或者,而不是使用 event.source ,您可以发送使用 self.clients.matchAll 的服务工作者的多个客户端的消息;再次在 service-worker.js

  self.addEventListener(消息,function(event){
self.clients.matchAll()。then(all => all.forEach(client => {
client.postMessage(Responding to+ event。数据);
}));
});

matchAll 接受一些过滤选项






<你已经说过你有麻烦让它上班。这是Chrome和Firefox中适用于我的完整版本:



service-worker.html p>

 <!doctype html> 
< html>
< head>
< meta charset =UTF-8>
< title>服务工作者< / title>
< / head>
< body>
(在控制台中查看)
< script>
(function(){
use strict;

if(!navigator.serviceWorker ||!navigator.serviceWorker.register){
console.log 这个浏览器不支持服务工作者);
return;
}

//听服务工作者的消息
navigator.serviceWorker.addEventListener 'message',function(event){
console.log(Got service from service worker:+ event.data);
});

//我们被控制?
if(navigator.serviceWorker.controller){
//是,发送我们的控制器一条消息
console.log(发送hi到控制器);
navigator.serviceWorker.controller.postMessage(hi);
} else {
//否,注册一个服务工作者来控制像我们这样的页面
//注意它赢了不要控制这个页面的这个实例,它只对它的范围内的页面生效
// *安装后*
navigator.serviceWorker.register(service-worker.js)
.then(function(registration){
console.log(Service worker registered,scope:+ registration.scope);
console.log(刷新页面来跟它说话);
//如果我们想要,我们可能会做location.reload();,以便我们被它控制
})
.catch(function(error){
console.log(服务工作者注册失败:+ error.message);
});
}
})();
< / script>
< / body>
< / html>

service-worker.js p>

  self.addEventListener(message,function(event){
//event.source.postMessage(\"Responding to + event.data;
self.clients.matchAll()。then(all => all.forEach(client => {
client.postMessage(Responding to+ event.data );
}));
});

如您所见,这是使用 self.clients.matchAll ,在其上注释出 event.source



如果我运行在两个窗口中,每个窗口的每个刷新都会向其他窗口发送消息(因为我使用 self.clients.matchAll ...)。


I am getting crazy and need your help. I am working on a serviceworker project and I am dealing with a javascript problem. I have to main files. The server.html file in which I call the external service-worker.js file in line 52. Here is my server.html file

<body>
    <div class="container"> 
        <h1>PRESENTER</h1>
        <div id="nicky">Nickname: <span id="nickname"></span></div>
        <form id="form-nick" name="form-nick" method="post" action="">
            <div class="formelement">
                <label name="labelnick" for="nick">Nickname:</label>
                <input type="text" id="nick" name="nick">
                <button type="submit">OK</button>
            </div>
        </form><br /><br />

        <h1>--></h1><div id="talker"></div>

        <button type="button" class="button blue" id="blue-display" disabled></button><br />

        <button type="button" class="button red" disabled></button><br />

        <button type="button" class="button lightblue" disabled></button>
    </div> <!-- container -->


    <script type="text/javascript">
        /* =============================================================================== */
        $(document).ready(function() {
            console.log("jquery ready function");

            $('#nick').focus();

            $('#form-nick').submit(function(){
                var form = $('#form-nick');
                var data = form.serialize();
                $.post('nicky.php', data, function(response) {
                    if (response) {
                        $('#nicky').show();
                        $('#nickname').text(response);
                        $('#form-nick').hide();
                        $('.blue, .red, .lightblue').fadeIn(100);

                        if('serviceWorker' in navigator){
                            // Register service worker
                            navigator.serviceWorker.register('service-worker.js').then(function(reg){
                                console.log("SW registration succeeded. Scope is "+reg.scope);

                            }).catch(function(err){
                                console.error("SW registration failed with error "+err);
                            });
                        }
                    } else {

                    }
                });
                return false;           
            });       
        });
    </script>
</body>

and here is the service-worker.js file

    // INSTALLING
// Install Service Worker
self.addEventListener('install', function(event){
    console.log('>> sw installed!');
});
// Service Worker Active
self.addEventListener('activate', function(event){
    console.log('>> sw activated!');
});
// Service Worker reveives message
self.addEventListener('message', function(event){
    console.log(event.data);
    send_message_to_all_clients(event.data);
    document.getElementById("talker").innerHTML = event.data;
});

In the last line I would like to insert the received message in the div "talker". But I always get the error service-worker.js:17 Uncaught ReferenceError: document is not defined

I took care, that I load the js-File after the document is loaded. Now I don't know what I do wrong. Thanks.

解决方案

Service workers — web workers in general — don't have direct access to the DOM at all. Instead, have the worker post the information to the main thread, and have code in the main thread update the DOM as appropriate. The theading model for JavaScript on browsers is that there is only one main UI thread (the default one your in-page code runs on), which can access the DOM. The others are walled off from it.

This page and this page both talk about messaging between service workers and clients. Here's a really simple example:

Script in the page loading the service worker:

(function() {
    "use strict";

    if (!navigator.serviceWorker || !navigator.serviceWorker.register) {
        console.log("This browser doesn't support service workers");
        return;
    }

    // Listen to messages from service workers.
    navigator.serviceWorker.addEventListener('message', function(event) {
        console.log("Got reply from service worker: " + event.data);
    });

    // Are we being controlled?
    if (navigator.serviceWorker.controller) {
        // Yes, send our controller a message.
        console.log("Sending 'hi' to controller");
        navigator.serviceWorker.controller.postMessage("hi");
    } else {
        // No, register a service worker to control pages like us.
        // Note that it won't control this instance of this page, it only takes effect
        // for pages in its scope loaded *after* it's installed.
        navigator.serviceWorker.register("service-worker.js")
            .then(function(registration) {
                console.log("Service worker registered, scope: " + registration.scope);
                console.log("Refresh the page to talk to it.");
                // If we want to, we might do `location.reload();` so that we'd be controlled by it
            })
            .catch(function(error) {
                console.log("Service worker registration failed: " + error.message);
            });
    }
})();

And in service-worker.js:

self.addEventListener("message", function(event) {
    event.source.postMessage("Responding to " + event.data);
});

That relies on event.source, which is supported by current versions of Chrome and Firefox.

Alternately, instead of using event.source, you can send a message to multiple clients of a service worker using self.clients.matchAll; again in service-worker.js:

self.addEventListener("message", function(event) {
    self.clients.matchAll().then(all => all.forEach(client => {
        client.postMessage("Responding to " + event.data);
    }));
});

matchAll accepts some filtering options.


You've said you're having trouble getting it to work. Here's a complete version of what's working for me in Chrome and Firefox:

service-worker.html:

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Service Worker</title>
</head>
<body>
(Look in the console.)
<script>
(function() {
    "use strict";

    if (!navigator.serviceWorker || !navigator.serviceWorker.register) {
        console.log("This browser doesn't support service workers");
        return;
    }

    // Listen to messages from service workers.
    navigator.serviceWorker.addEventListener('message', function(event) {
        console.log("Got reply from service worker: " + event.data);
    });

    // Are we being controlled?
    if (navigator.serviceWorker.controller) {
        // Yes, send our controller a message.
        console.log("Sending 'hi' to controller");
        navigator.serviceWorker.controller.postMessage("hi");
    } else {
        // No, register a service worker to control pages like us.
        // Note that it won't control this instance of this page, it only takes effect
        // for pages in its scope loaded *after* it's installed.
        navigator.serviceWorker.register("service-worker.js")
            .then(function(registration) {
                console.log("Service worker registered, scope: " + registration.scope);
                console.log("Refresh the page to talk to it.");
                // If we want to, we might do `location.reload();` so that we'd be controlled by it
            })
            .catch(function(error) {
                console.log("Service worker registration failed: " + error.message);
            });
    }
})();
</script>
</body>
</html>

service-worker.js:

self.addEventListener("message", function(event) {
    //event.source.postMessage("Responding to " + event.data);
    self.clients.matchAll().then(all => all.forEach(client => {
        client.postMessage("Responding to " + event.data);
    }));
});

As you can see, that's the version using self.clients.matchAll, with the commented out event.source version above it.

If I run that in two windows, each refresh of each window sends a message to the other windows (because I'm using self.clients.matchAll...).

这篇关于由网络工作者访问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆