资讯专栏INFORMATION COLUMN

搞笑向, 面向IE8的webworker-ployfill

CoyPan / 3242人阅读

摘要:首先,这是一篇不严谨的博文。本文仅供参考,无法在实际生产中运用。首先,在书写逻辑上是同步的,但其实加载这个行为是异步的。其次,依赖事件与主线程进行沟通,中间经过的数据会被。

首先,这是一篇不严谨的博文。

本文仅供参考,无法在实际生产中运用。

在捯饬文件分片上传的过程中,我总是觉得单线程太慢了。

于是想,用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 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 = {};

    // debug
    window.__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;

智障儿童欢乐多。

来,让我们玩一把吧,下面是测试代码。




    
    测试23333


    
        {{text}}
    
    
    
    

// 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.

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95622.html

相关文章

  • 再和“面对象”谈恋爱 - 面对象编程概念(三)

    摘要:说到底面向对象才是程序语言的根本。其实面向对象编程说的就是自定义对象。里并没有类的概念,所以严格上来讲这是个假的面向对象里的面向对象编程现在好了,终于听到别人鄙视我们了,给我们提供了类这个概念,其实是向传统语言更靠齐了。 通过前两篇文章,我们了解了对象的概念以及面向对象里的相关概念等知识,那前面说了对象分类里的前两种,这篇文章要详细去说第三种自定义对象,那真正的好戏这就来了! 面向对象...

    Cruise_Chan 评论0 收藏0
  • QQ邮箱是如何泄密:JSON劫持漏洞攻防原理及演练

    摘要:下面就是对这种攻击原理的介绍以及预防方法。针对该漏洞的特点,通过覆盖数组构造函数以窃取暴露返回数组,而现在大多数浏览器还无法防范这种攻击。在上周的挪威开发者大会上,我做了一个针对劫持漏洞的演示。 注:作者发表这篇文章的时间较早,某些方法可能并不是最好的解决方案,但针对这种漏洞进行的攻击还依然可见,如早期的:QQMail邮件泄露漏洞。直到现在,你在某些邮箱打开一个外部链妆,依然会有安全警...

    khlbat 评论0 收藏0
  • 从“云”到“雾”:云计算将死亡,取而代之是分布式点对点网络

    摘要:随着服务器转移到云端,比如亚马逊或谷歌的数据中心的亚马逊或谷歌的计算机,靠近这些地方的网络需要有令人难以置信的吞吐量来处理所有这些数据。已经有一些协议使用这些技术来构建符合我们需求的分布式存储。 云将会走向终结。我知道,这是一个大胆的结论,也许听起来有点疯狂。但请容忍我,让我说下去。一直以来,都有这样的一个传...

    mengbo 评论0 收藏0
  • 从“云”到“雾”:云计算将死亡,取而代之是分布式点对点网络

    摘要:随着服务器转移到云端,比如亚马逊或谷歌的数据中心的亚马逊或谷歌的计算机,靠近这些地方的网络需要有令人难以置信的吞吐量来处理所有这些数据。已经有一些协议使用这些技术来构建符合我们需求的分布式存储。 云将会走向终结。我知道,这是一个大胆的结论,也许听起来有点疯狂。但请容忍我,让我说下去。一直以来,都有这样的一个传统观点:运行服务器的应用程序,无论是Web应用还是移动应用的后台,未来都会在云端。亚...

    teren 评论0 收藏0
  • 关于前端跨域总结

    摘要:前端开发中,跨域使我们经常遇到的一个问题,也是面试中经常被问到的一些问题,所以,这里,我们做个总结。同源策略限制了一下行为和无法读取和对象无法获取请求发送不出去常见的跨域场景所谓的同源是指,域名协议端口均为相同。 前端开发中,跨域使我们经常遇到的一个问题,也是面试中经常被问到的一些问题,所以,这里,我们做个总结。小小问题,不足担心 原文地址:YOU-SHOULD-KNOW-JS 什么是...

    muddyway 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<