博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
前端黑魔法:webworker动态化,无需JS文件创建worker
阅读量:5015 次
发布时间:2019-06-12

本文共 2445 字,大约阅读时间需要 8 分钟。

前言

前几天,我和一位知乎网友讨论这个问题的时候,觉得这非常有意思,所以写了这篇文章作为记录
本文的思路和项目代码来源于知友,我加以修饰以更符合理解的需求。
 
本文所用代码已经得到当事人授权,请看:
非常感谢他的理解和鼓励
 

作者初始代码地址

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

 

 

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

Webworker,我其实一直觉得用法比较生硬,因为似乎需要创建额外的JS文件才能运行,就像下面这样
var worker =new Worker('work.js’)
 
这意味着,你需要额外创建一个js文件。这种方式让我觉得有些“古板”。因为JS操纵文件的能力很差,如果想要创建文件,当然方法也有,参考:
 
但是问题在于,如果想要创建文件,JS的文件创建往往离不开下载!我原本只是想“悄无声息”地创建一个文件,但结果JS在创建的时候突然弹出一个下载框,这可让人受不了。啊,难受。(此处应有[我太难了]表情包)。
 
也就是,这时候的webWorker是“静态”的,是需要额外JS文件的,是受约束的。
 

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

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

 
这真是一个令人兴奋的信息。
 
试看看他的操作:
// 文件名为main.jsfunction 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.jsfunction 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得到的字符串居然是有作用的。信息差,也是会造成差距的。所以工程上也经验和前瞻也同样重要。

其他参考资料

  • worker-loader源码: 

转载于:https://www.cnblogs.com/penghuwan/p/11546407.html

你可能感兴趣的文章
5大主浏览器css3和html5兼容性大比拼
查看>>
hdu-5894 hannnnah_j’s Biological Test(组合数学)
查看>>
scss常规用法
查看>>
css定位position属性深究
查看>>
android中不同版本兼容包的区别
查看>>
Static 与 new 的问题【待解决】
查看>>
xml
查看>>
在 mvc4 WebApi 中 json 的 跨域访问
查看>>
敏捷开发文章读后感
查看>>
xposed获取context 的方法
查看>>
html5 canvas 图像处理
查看>>
He who hesitates is Lost
查看>>
php中引用&的真正理解-变量引用、函数引用、对象引用
查看>>
关于<form> autocomplete 属性
查看>>
OutOfMemory
查看>>
LeetCode:组合总数III【216】
查看>>
Thinkphp框架回顾(三)之怎么实现平常的sql操作数据库
查看>>
虚函数的效率问题
查看>>
POJ 1860 Currency Exchange(SPFA 判断有无“正”环)
查看>>
广告地址屏蔽
查看>>