前言

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

作者初始代码地址

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

通过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得到的字符串居然是有作用的。信息差,也是会造成差距的。所以工程上也经验和前瞻也同样重要。

其他参考资料

前端黑魔法:webworker动态化,无需JS文件创建worker的更多相关文章

  1. 前端开发面试题收集 JS

    前端开发面试题收集-JS篇 收集经典的前端开发面试题 setTimeout的时间定义为0有什么用? javascript引擎是单线程处理任务的,它把任务放在队列中,不会同步执行,必须在完成一个任务后才 ...

  2. 前端迷思与React.js

    前端迷思与React.js 前端技术这几年蓬勃发展, 这是当时某几个项目需要做前端技术选型时, 相关资料整理, 部分评论引用自社区. 开始吧: 目前, Web 开发技术框架选型为两种的占 80% .这 ...

  3. 【前端芝士树】Vue.js面试题整理 / 知识点梳理

    [前端芝士树] Vue.js 面试题整理 MVVM是什么? MVVM 是 Model-View-ViewModel 的缩写. Model代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑. ...

  4. 前端开发之走进Vue.js

    Vue.js作为目前最热门最具前景的前端框架之一,其提供了一种帮助我们快速构建并开发前端项目的新的思维模式.本文旨在帮助大家认识Vue.js,了解Vue.js的开发流程,并进一步理解如何通过Vue.j ...

  5. 前端开发必须知道的JS(二) 闭包及应用

    http://www.cnblogs.com/ljchow/archive/2010/07/06/1768749.html 在前端开发必须知道的JS(一) 原型和继承一文中说过下面写篇闭包,加之最近越 ...

  6. css-dialog样式实现弹框蒙层全屏无需JS计算高度兼容IE7

    <!DOCTYPE html><html><head>  <meta charset="UTF-8">  <title> ...

  7. 前端开发必须知道的JS之闭包及应用

    本文讲的是函数闭包,不涉及对象闭包(如用with实现).如果你觉得我说的有偏差,欢迎拍砖,欢迎指教. 在前端开发必须知道的JS之原型和继承一文中说过下面写篇闭包,加之最近越来越发现需要加强我的闭包应用 ...

  8. 为什么43%前端开发者想学Vue.js

    根据JavaScript 2017前端库状况调查 Vue.js是开发者最想学的前端库.我在这里说明一下我为什么认为这也是和你一起通过使用Vue构建一个简单的App应用程序的原因. 我最近曾与Evan ...

  9. 从cocos2d-html5中提取出来的,用做前端开发的框架——cc.js

    从cocos2d-html5中提取出来的,用做前端开发的框架——cc.js /************************************************************* ...

随机推荐

  1. 本地VSCode编辑远程服务器文件

    前言 先说下我的场景:服务器搭设了一系列复杂环境,然后需要使用PHP实现某些功能 选这种远程编辑的原因: 首先PHP打死我也不想装(这个现在是出了VB外最惹人厌的语言了) 然后环境比较复杂,本地装下比 ...

  2. wordpress修改登录密码

    wordpress忘记密码更改 网上搜到的方法: 1.后台邮件重置: 2,phpmyadmin登录数据库,执行mysql语句或者在wp_users表中重置密码: 3,利用php文件重置. 这是提供一种 ...

  3. Day 01--选题与设计(一)

    1.第一天我们主要确定了软件课设的项目,做一个学校内食堂订送餐的微信小程序.我们大体的设计思路是:可以实现学生身份的认证,幷使学生们能自行选择校园内的食堂,挑选各个食堂各个窗口菜谱上可以选择的菜,选择 ...

  4. IDEA导入spring-boot-plus(二)

    IDEA导入spring-boot-plus 安装lombok插件 !!!请先确保IDEA已安装lombok插件!!! IDEA在线安装lombok插件 IDEA离线下载安装lombok 如果在线安装 ...

  5. 单元测试之NUnit三

    NUnit 分三篇文章介绍,入门者可阅读文章,有基础者直接参考官方文档.初次写博客,望大家指点. 导航: 单元测试之NUnit一 单元测试之NUnit二 单元测试之NUnit三 除了Assert断言外 ...

  6. 宝塔安装Lsky Pro图床教程

    欢迎访问我的个人博客皮皮猪:http://www.zhsh666.xyz Lsky Pro图床是一个支持本地.阿里云 OSS.腾讯云 COS.七牛云.又拍云等储存方式的基于PHP的开源图床. 项目主页 ...

  7. C#数据结构_排序

    /** * 冒泡排序 * * @param array * @return */ public static int[] bubbleSort(int[] array) { if (array.len ...

  8. Java多线程之线程的暂停

    Java多线程之线程的暂停 下面该稍微休息一下了呢……不过,这里说的是线程休息,不是我们哦.本节将介绍一下让线程暂停运行的方法. 线程Thread 类中的sleep 方法能够暂停线程运行,Sleep ...

  9. Java IO体系之File类浅析

    Java IO体系之File类浅析 一.File类介绍 位于java.io下的Java File类以抽象的方式代表文件名和目录路径名.该类主要用于文件和目录的创建.文件的查找和文件的删除等.File对 ...

  10. Win10环境下安装压缩包版本MySQL-8.0.13

    准备工作 系统环境:Windows 10 1803版本: 压缩包:MySQL-8.0.13 Windows zip包下载: 安装过程 1. 加载安装包到你的安装目录 将下载的MySQL压缩包解压并移到 ...