专栏首页彭湖湾的编程世界前端黑魔法:webworker动态化,无需JS文件创建worker

前端黑魔法:webworker动态化,无需JS文件创建worker

前言

前几天,我和一位知乎网友讨论这个问题的时候,觉得这非常有意思,所以写了这篇文章作为记录

本文的思路和项目代码来源于知友 @simon3000,我加以修饰以更符合理解的需求。

本文所用代码已经得到当事人授权,请看:

非常感谢他的理解和鼓励

作者初始代码地址

(进入项目页面,里面的original-version目录下就是作者的最初的代码)

https://github.com/penghuwan/flex-webworker 

通过JS文件和路径创建webworker带来的问题

Webworker,我其实一直觉得用法比较生硬,因为似乎需要创建额外的JS文件才能运行,就像下面这样

var worker =new Worker('work.js’)

这意味着,你需要额外创建一个js文件。这种方式让我觉得有些“古板”。因为JS操纵文件的能力很差,如果想要创建文件,当然方法也有,参考:https://github.com/eligrey/FileSaver.js/

但是问题在于,如果想要创建文件,JS的文件创建往往离不开下载!我原本只是想“悄无声息”地创建一个文件,但结果JS在创建的时候突然弹出一个下载框,这可让人受不了。啊,难受。(此处应有[我太难了]表情包)。

也就是,这时候的webWorker是“静态”的,是需要额外JS文件的,是受约束的。

四次转换,将一个普通函数强行变成WebWorker

但是 @simon3000 的建议让我眼前一亮!他告诉我,根据他使用webworker-loader(webpack技术栈)的经验,有一种连续转换的方式可以直接将一个普通函数变成WebWorker

这真是一个令人兴奋的信息。

试看看他的操作:

// 文件名为main.js
function work () {
  onmessage = ({data: {message}}) => {
    console.log ('i am worker, receive:' + message);
    postMessage ({result: 'message from worker'});
  };
}

const runWorker = f => {
  const worker = new Worker (
    URL.createObjectURL (new Blob ([`(${f.toString ()})()`]))
  );

  worker.onmessage = ({data: {result}}) => {
    console.log ('i am main thread, receive:' + result);
  };

  worker.postMessage ({message: 'message from main thread'});
};

const testWorker = runWorker (work);

这段代码是我在他的代码基础上简化的

输出结果:

用Promise和闭包的方式去改造

我们再让它更通用一些,用Promise和闭包的方式去改造它,把runworker函数改造成一个makeworker函数

// 文件名为index.js
function work () {
  onmessage = ({data: {jobId, message}}) => {
    console.log ('i am worker, receive:-----' + message);
    postMessage ({jobId, result: 'message from worker'});
  };
}

const makeWorker = f => {
  let pendingJobs = {};

  const worker = new Worker (
    URL.createObjectURL (new Blob ([`(${f.toString ()})()`]))
  );

  worker.onmessage = ({data: {result, jobId}}) => {
    // 调用resolve,改变Promise状态
    pendingJobs[jobId] (result);
    // 删掉,防止key冲突
    delete pendingJobs[jobId];
  };

  return (...message) =>
    new Promise (resolve => {
      const jobId = String (Math.random ());
      pendingJobs[jobId] = resolve;
      worker.postMessage ({jobId, message});
    });
};

const testWorker = makeWorker (work);

testWorker ('message from main thread').then (message => {
  console.log ('i am main thread, i receive:-----' + message);
});

输出结果

总结

这次探讨告诉我们什么道理呢?

  • 第一,function.toString得到的并不是一个没有意义的字符串,它是完全可以被用来运行的
  • 第二,通过这种方式,webworker不需要借助额外的JS文件了,webworker完全动态化和自由化,你可以在主线程中创建任意个webworker!
  • 第三,我通过这次的交谈了解到一个道理,编程除了考量逻辑思维,信息差也是考量的一大因素。我之前也想过用webworker做这些事情,可是我不知道能用这样的四重转换呀!我也不知道function.toString得到的字符串居然是有作用的。信息差,也是会造成差距的。所以工程上也经验和前瞻也同样重要。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【CSS】Houdini, CSS的成人礼

    简单地讲,Paint API就是允许你通过JavaScript注册一个背景函数,类似于linear-gradient()那种,在定义时候可以提供Canvas的2...

    外婆的彭湖湾
  • 【计算机网络】网络层学习笔记:总结IP,NAT和DHCP

    前言:这篇文章是学习网络层协议时候总结的笔记,前面的主要部分介绍的都是IP协议, 后半部分介绍NAT协议和DHCP协议 参考书籍 《计算机网络-自顶向下》   ...

    外婆的彭湖湾
  • 【react】关于react框架使用的一些细节要点的思考

    ( _(:3 」∠)_给云友们提个建议,无论是API文档还是书籍,一定要多看几遍!特别是隔一段时间后,会有意想不到的收获的) 这篇文章主要是写关于学习react...

    外婆的彭湖湾
  • #凯哥讲数据中台#深度剖析数据中台提供的数据服务

    业界常用的数据服务包括五种类型,Data API,Event Hub,Database,File,Terminal & APP。

    凯哥
  • 要做软件工程师,而不是前端工程师

    最近几个月一直有些事情没有想通,但可幸的是,有些问题的答案逐渐开始明朗起来了。好久没写文章,籍此献上一篇短文。

    李成熙heyli
  • 可视化告诉你,大数据究竟是什么?

    大数据文摘
  • Windows 系统中Python常用的

    py3study
  • 金融科技时代,大数据提高传统银行转型成功率

    金融科技的创新力量已经深深影响到我国金融业的发展进程,大数据、人工智能、云计算等前沿技术正在改变着金融业的旧结构、旧模式,传统金融机构特别是银行的转型迫在眉睫。...

    企鹅号小编
  • 从阿里巴巴买《南华早报》看互联网巨头的话语权布局

    去年阿里巴巴大举投资中国互联网时有人说马云想要买下半个中国互联网,现在看来马云的野心显然不只是互联网。阿里巴巴近日收购香港著名媒体《南华早报》之后,其媒体布局在...

    罗超频道
  • Centos7 搭设GitBook环境

    在Centos7下搭建GitBook环境,主要需要安装几个组件:nodejs、gitbook、git 其中nodejs可以使用nvm进行版本切换管理。

    Devops海洋的渔夫

扫码关注云+社区

领取腾讯云代金券