JavaScript Worker 另类玩法

159 阅读5分钟
原文链接: mp.weixin.qq.com

Web Workers API 的 Worker 接口代表一个可以轻松创建的后台任务,正常情况下,需要引用一个js脚本文件,那么有没有可能直接使用而不用"加载"JS脚本呢?

Worker 是什么

Web Workers API 

(https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API)的 Worker 接口代表一个可以轻松创建的后台任务,并可以将消息发送回其创建者。创建一个工作程序只要简单的调用Worker() 构造函数,并指定一个要在工作线程中运行的脚本。

兼容性

http://caniuse.mojijs.com/Home/Html/item/key/webworkers/index.html

Worker正常使用:

est.js 线程文件

addEventListener("message",function (e) {    console.log(e.data)
})//...

 html

  var woker = new Worker("test.js");
    woker.postMessage("test");

输出:

线程生成过程

那么中间的加载js过程与当前网络速度相关,如果不稳定可能会出现加载时间加长或加载失败。如果开启多个,那么会生成多个请求。

下图生成三个Worker,加载同个js。

假如要建立多少不同的线程处理,还需要建立多个不同的js,不能动态的处理线程。

var woker = new Worker("test1.js");
    woker.postMessage("test1");var woker = new Worker("test2.js");
    woker.postMessage("test2");var woker = new Worker("test3.js");
    woker.postMessage("test3");

那么能不能动态的处理线程呢?不需要“加载”js文件,把脚本传到线程内执行?

Worker 要加载js,那么可以虚拟一个文件给它吗?

Blob

Blob 对象表示一个不可变、原始数据的类文件对象。Blob 表示的不一定是JS原生格式的数据。File 接口基于Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。

第一步,把字符变成一个文件(Blob):

生成Blob:

window.BlobBuilder =  window.BlobBuilder ||    window.WebKitBlobBuilder ||    window.MozBlobBuilder ||    window.MSBlobBuilder;//兼容Blobvar createBlob = function(data,mimeType){    var blob;    try {
        blob = new Blob([data], {type: mimeType})
    }catch (e)
    {        if(e.name == "TypeError" &&  BlobBuilder )
        {            var bb = new BlobBuilder();            if (typeof  data == "string")
            {                var arr = data
            }else
            {                if (data instanceof ArrayBuffer)
                {
                    data = new DataView(data)
                }                var arr = data.buffer;
            }


            bb.append(arr)
            blob =bb.getBlob(mimeType)

        }

    }    return blob;
} 

 测试:

function test() {            console.log("test")
    }    console.log(test.toString())

 输出:

生成一个js的Blob文件:

 function test() {            console.log("test")
    }   var str = test.toString();    var blob = createBlob(str,"application/javascript");    console.log(blob)

把Blob变成一个可访问的地址:    (URL.createObjectURL 传送门)

function test() {            console.log("test")
    }   var str = test.toString();    var blob = createBlob(str,"application/javascript");    var jssrc = URL.createObjectURL(blob)    console.log(jssrc)

测试Worker加载 

   function test() {        addEventListener("message",function (e) {            console.log(e.data)        })    }   var str = test.toString() + ";\n test();";    //";\n test();"; 执行test();    var blob = createBlob(str,"application/javascript");    var jssrc = URL.createObjectURL(blob)    var woker = new Worker(jssrc);    woker.postMessage("test");

生成的线程:

输出:

现在的流程:

使用Blob方式后:

加载时间大概10-22ms ,可以动态的创建不同的线程。

开启多个相同的线程可以使用同一个Blob。

实时运算:

根据Blob方式实现了一套实时运算的线程封装,直接使用函数运算:

        var i =0;        //run([参数],线程函数) 返回Promise
        TGMG.thread.Thread.run(["test",[]],function (value,data) {            //线程内
            console.log(value,data)           console.log("i=",i);            var str = ""
            for (var i=0;i<100000;i++)
            {
                str += "--"
            }            //返回数据
            result(str)            //关闭线程
            close()
        }).then(function (value) {            //主线程
            //接收返回参数
            console.log(value)
        })

 输出:

变量 i 是主线程的变量,所以在线程内是访问不到的,得到是undefined

方式2:

 function test(value) {            return value + value
        }        var thread=  new TGMG.thread.Thread(
                {                    run:function (a,b,c) {                        //线程内
                        console.log(a,b,c)
                        result(test(a),test(b))
                        result(test(c),test(a))                        //关闭线程
                        close()
                    },                    result:function (valueA,valueB)                    {                        console.log(valueA,valueB)
                    }
                    ,method:test.toString()
                })
        thread.start(1,2,3)

 生成的线程:

输出:

结束

使用Blob方式加载后,可以不再使用实体js脚本来开启了,减少了维护的成本。实时创建,实时运算。


作者:腾讯IEG事业群\创意设计部\多媒体开发组员工——林雨

   前端NEXT学位课程第八期开始招生!

  感兴趣的同学赶紧 点击原文了解详情吧~

腾讯NEXT学位

求职干货 | 前辈blog  | 前端课程