搞笑向, 面向IE8的webworker-ployfill
首先,這是一篇不嚴謹的博文。
本文僅供參考,無法在實際生產中運用。
在捯飭文件分片上傳的過程中,我總是覺得單線程太慢了。
于是想,用webWorker唄。
首先,我們可以查看一下WebWorker的兼容性。根據MDN文檔來看,主流瀏覽器都兼容。
但有個問題,MDN表示WebWorker只支持到IE10.如果要兼容到ie8,勢必要維護兩份上傳代碼,怎么破???
發揮我們聰明才智的時候到了
好了,我們可以開始開腦洞了,
要聲明的是,我們只是實現Worker這個假的構造函數。
首先,WebWorker在書寫邏輯上是同步的,但其實加載Worker這個行為是異步的。
其次,WebWorker依賴事件與主線程進行溝通,中間經過的數據會被toString()。
再者,WebWorker的api比較簡單,模擬起來也比較方便。
首先來看Worker的interface定義
[Constructor(USVString scriptURL, optional WorkerOptions options), Exposed=(Window,Worker)] interface Worker : EventTarget {void terminate();void postMessage(any message, optional sequence<object> transfer = []);attribute EventHandler onmessage;attribute EventHandler onmessageerror; };dictionary WorkerOptions {WorkerType type = "classic";RequestCredentials credentials = "omit"; // credentials is only used if type is "module"DOMString name = ""; };enum WorkerType { "classic", "module" };Worker includes AbstractWorker;Worker接口繼承了EventTarget,所以還能使用addEventListener removeEventListener這倆api
所以我們要實現一個假的Worker,需要實現以下內容:
-
加載Worker腳本
- 加載規則為同域名,從根目錄開始尋找。
- 暫不做blob生成,對本篇文章主題而言沒有意義。
-
實現以下內容
- 實現onmessage
- 實現onmessageerror (文章中暫不實現)
- 實現close
- 實現terminate (文章中暫不實現)
- 實現addEventListener (文章中暫不實現)
- 實現removeEventListener (文章中暫不實現)
- 實現個假事件。
一步一步來
為了模擬Worker的同步書寫方式
我們需要實現一個同步加載腳本的方法?(●゚ω゚●)
注:在現代瀏覽器里已經不贊成使用了
(function (root) {var cache = {};// debugwindow.__rc = cache;var module = {};module.exports = null;var config = {rootPath: ''};function hash(str) {var hash = 5381,i = str.length;while(i) {hash = (hash * 33) ^ str.charCodeAt(--i);}/* JavaScript does bitwise operations (like XOR, above) on 32-bit signed* integers. Since we want the results to be always positive, convert the* signed int to an unsigned by doing an unsigned bitshift. */return hash >>> 0;}var defaultShimFunction = function (code, f) {if (f) {return f.replace('[[code]]', code);}return code;};root.require = function (scriptPath, shim) {var path = scriptPath;shim = shim || '';if (/^(\/|https?:\/\/)/.test(scriptPath) !== true) {path = config.rootPath + scriptPath;}if (/\.js$/.test(path) === false) {path += '/index.js';}var keyName = path + '?hash=' + hash(shim);if (cache[path]) {if (cache[keyName]) {return cache[keyName]}eval(defaultShimFunction(cache[path], shim));return cache[keyName] = module.exports;}var request = new XMLHttpRequest();request.open('GET', path, false);request.send(null);if (request.status === 200) {cache[path] = request.responseText;eval(defaultShimFunction(cache[path], shim));cache[keyName] = module.exports;}return cache[keyName];};root.require.config = function (opts) {for (var i in opts) {config[i] = opts[i]}}; }(window));(?′?`?)上述代碼不要在意,主要實現的功能其實就是特別智障的在瀏覽器里同步加載commonjs模塊。。。
加了個墊片,方便操作
萬事具備,只欠東風
來吧,直接上代碼,worker-ployfill.js
window.__wbus = {_lis: {},on: function (evt, fn) {this._lis[evt] = fn;},off: function (evt) {if (!evt) {this._lis = {};return;}delete this._lis[evt];delete this._lis['close' + evt];},emit: function (evt, data) {this._lis[evt] && this._lis[evt](data);} };function copy (a) {if (typeof a === 'object') {var c = JSON.stringify(a);return JSON.parse(c);}return a; }function FakeEvent (data, id) {this.data = copy(data);this.type = 'message';this.id = id; }var uuid = 1;var FakeWorker = function (p) {var self = this;self._id = uuid++;window.__wbus.on(self._id, function (data) {var Fe = new FakeEvent(data, self._id);self.onmessage && self.onmessage.call(Fe, Fe);});window.__wbus.on('close' + self._id, function (data) {self.terminates();});var path = location.protocol + '//' + location.host + '/' + p;var wf = require(path, 'module.exports = function () {\var self = {};\self.postMessage = function (data) {\window.__wbus.emit(' + self._id + ', data);\};\self.onmessage = function () {};\self.close = function () { window.__wbus.emit(close' + self._id + ') };\[[code]]\;return self;\}\');this.worker = wf(); };FakeWorker.prototype.onmessage = function () { };FakeWorker.prototype.postMessage = function (data) {if (!this.worker) {throw new ReferenceError('Worker already stoped!');}var d = new FakeEvent(data, this._id);this.worker.onmessage && this.worker.onmessage.call(d, d); };FakeWorker.prototype.terminates = function () {this.worker = null;window.__wbus.off(this._id); };module.exports = FakeWorker;智障兒童歡樂多。
來,讓我們玩一把吧,下面是測試代碼。
<!DOCTYPE html> <html> <head><meta charset="utf-8"><title>測試23333</title> </head> <body><span>{{text}}</span><script type="text/javascript" src="/static/js/require.js"></script><script type="text/javascript">require.config({rootPath: '/node_modules/'});</script><script type="text/javascript">var Worker = require('/static/js/worker-ployfill.js');var cpus = require('cpus/browser.js')().length;var workers = [];for (var i = 0; i < cpus; i ++) {workers[i] = new Worker('static/js/worker-test.js');}workers.forEach((item) => {item.onmessage = function (e) {console.log('main thread'),console.log('thread id: %s', e.id);console.log('msg: %s', JSON.stringify(e.data));};item.postMessage({message: 'message from main'});})</script> </body> </html> // worker-test.js self.onmessage = function (e) {console.log('worker thread'),console.log('thread id: %s', e.id);console.log('msg: %s', JSON.stringify(e.data));self.postMessage({message: 'from FackWorker'}); };
你看,智障系列
233333333.
總結
以上是生活随笔為你收集整理的搞笑向, 面向IE8的webworker-ployfill的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VueJS ReactJS 如何?听听
- 下一篇: golang日期时间格式format()