天天看點

JavaScript Worker 另類玩法

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

JavaScript Worker 另類玩法

Worker正常使用:

est.js 線程檔案

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

複制

 html

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

複制

輸出:

JavaScript Worker 另類玩法

線程生成過程

JavaScript Worker 另類玩法

那麼中間的加載js過程與目前網絡速度相關,如果不穩定可能會出現加載時間加長或加載失敗。如果開啟多個,那麼會生成多個請求。

下圖生成三個Worker,加載同個js。

JavaScript Worker 另類玩法

假如要建立多少不同的線程處理,還需要建立多個不同的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())           

複制

 輸出:

JavaScript Worker 另類玩法

生成一個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)           

複制

JavaScript Worker 另類玩法

測試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");           

複制

生成的線程:

JavaScript Worker 另類玩法

輸出:

JavaScript Worker 另類玩法

現在的流程:

JavaScript Worker 另類玩法

使用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)
        })           

複制

 輸出:

JavaScript Worker 另類玩法

變量 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)           

複制

 生成的線程:

JavaScript Worker 另類玩法

輸出:

JavaScript Worker 另類玩法

結束

使用Blob方式加載後,可以不再使用實體js腳本來開啟了,減少了維護的成本。實時建立,實時運算。

作者:騰訊IEG事業群\創意設計部\多媒體開發組員工——林雨