• js多线程的实现-Worker


    大家都知道js是基于单线程的,而这个线程就是浏览器的js引擎。
    首先来看一下大家用的浏览器都具有那些线程吧。

    如果我们要执行一些耗时的操作,比如加载一张很大的图片,我们可能需要一个进度条来让用户进行等待,在等待的过程中,整个js线程会被阻塞,后面的代码不能正常运行,这可能大大的降低用户体验,这时候我们就期望拥有一个工作线程来处理这些耗时的操作。在传统的html时代是基本不可能实现的,而现在,我们拥有一种叫做worker的东西。它是js里的一个类,而我们只需要创建它的实例就可以使用它。

    var worker = new Worker(js_file_path);

    参数填上你的js文件的路径,这个js文件将会在浏览器新开的线程里运行,而与原先的js引擎的线程并不影响。

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>worker</title>
    </head>
    <body>
        <input type="text" name="ipt" id="ipt" value=""><br>
        <input type="button" name="start" id="start" value="start">
        <input type="button" name="stop" id="stop" value="stop">
        <input type="button" name="alert" id="alert" value="alert">
        <script type="text/javascript">
            var ipt = document.getElementById("ipt");
            var start = document.getElementById("start");
            var stop = document.getElementById("stop");
            var alt = document.getElementById("alert");
            var worker = new Worker("js/test.js");
            function getMessage() {
                worker.onmessage = function() {
                    ipt.value = event.data;
                }
            }
            getMessage();
            stop.addEventListener("click", function() {
                //用于关闭worker线程
                worker.terminate();
            })
            start.addEventListener("click", function() {
                //开启worker线程
                worker = new Worker("js/test.js");
                getMessage();
            })
            alt.addEventListener("click", function() {
                alert("i'm a dialog");
            })
        </script>
    </body>
    </html>

    test.js里的代码,也就是存在于worker线程里的代码

    var i = 0;
    function mainFunc(){
        i++;
        //把i发送到浏览器的js引擎线程里
        postMessage(i);
    }
    var id = setInterval(mainFunc,1000);

    运行起来我们会发现

    点击"alert"里的“确定”后,它的数值并非2,而是一个比2更大的数

    虽然dialog的弹出会阻塞js引擎线程,但是并不影响worker线程的运行,所以,在我们点击确定后,只是在js引擎线程上更新了新的内容,而数值是一直在跑动的,这就说明worker线程和原本的js线程互不影响.

    那么既然互不影响,两个线程之间要怎么来联系呢,答案其实已经在代码里了,那就是onPostMessage 和 onmessage这两个函数,其中onPostMessage(data)的参数是你要传递的数据,而onmessage是一个回调函数,只有在接受到数据时,onmessage会被回调,onmessage有一个隐藏的参数,那就是event,我们可以用event.data获取到传递过来的数据来更新主线程。

    使用worker线程应注意的是,所有js里集成的对象都在js线程里,而并非worker线程。
    例如我们在worker线程里写上:

    var a = document.getElementById("a");

    结果你会得到一条Error,告诉你找不到document,或者document is undefined。所以我们尽量把需要的东西都写到主线程里,而只把耗时的操作写到worker线程里。

    注意:如果所运行的html页面在本地启动脚本,chrome会报错。

    原因分析:Chrome从本地文件运行脚本时不允许加载web worker.

    解决办法:启动web容器,通过服务器访问页面资源。比如:localhost:8081/worker.html 或这换种浏览器试试。

    参考: https://www.cnblogs.com/haodawang/articles/5850822.html

  • 相关阅读:
    项目管理理论与实践(6)——利用Excel制作项目文档的设计技巧
    项目管理理论与实践(5)——UML应用(下)
    【工具推荐】ELMAH——可插拔错误日志工具
    ExtJs实践(1)——Ext.extend的用法
    设计一套基于NHibernate二级缓存的MongoDB组件(上)
    ExtJs实践(3)——xtype名称与控件对应
    项目管理理论与实践(2)——软件需求分析
    【培训稿件】构建WCF面向服务的应用程序(包含ppt,源代码)
    ExtJs实践(5)——解决在GridPanel中使用bbar或者tbar的分页条的宽度自适应问题
    项目管理理论与实践(3)——如何进行有效的项目管理
  • 原文地址:https://www.cnblogs.com/starrk-01/p/10282377.html
Copyright © 2020-2023  润新知