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事業群\創意設計部\多媒體開發組員工——林雨