无缝 Web 工作者和工作线程 -threads.js
快速在 Worker 中运行跨平台 Javascript / TypeScript 代码。使用透明 API,省去繁琐步骤。
经过半年的测试,threads.js v1.0 终于发布了。它允许你以直观的方式使用 Web Worker 和工作线程,提供线程池等功能,可在 Web 客户端和 Node.js 中运行,并且大小不到 10kB!
使用工人的好处已经在很多其他文章中讨论过了,所以这里是要点:
- 利用所有可用的 CPU 能力来运行繁重的 CPU 密集型任务
- 将所有非渲染代码移出主线程,以确保流畅的动画和响应式的用户界面(Web Worker)
- 隔离软件模块,限制它们通过消息传递进行通信
虽然 Web Worker 和 Worker 线程的 API 很相似,但遗憾的是它们并不完全兼容。此外,它们只是一些底层的构建块:创建 Worker、订阅消息、发送消息等等。
如果你向 Worker 发送一些消息,其中一条导致 Worker 抛出异常,会发生什么?调用代码很可能永远不会知道发生了错误——它只是不会收到响应消息而已。然后就是所有的粘合代码……
透明 API 的功能
进入正题……threads.js!让我们编写一个简单的工作器来为我们哈希密码。
// workers/auth.js
import sha256 from "js-sha256"
import { expose } from "threads/worker"
expose({
hashPassword(password, salt) {
return sha256(password + salt)
}
})
现在让我们编写主线程的代码——生成一个新的工作者并对密码进行哈希处理。
// master.js
import { spawn, Thread, Worker } from "threads"
async function main() {
const auth = await spawn(new Worker("./workers/auth"))
const hashed = await auth.hashPassword("Super secret password", "1234")
console.log("Hashed password:", hashed)
await Thread.terminate(auth)
}
main().catch(console.error)
很简单。在 Worker 中暴露一个函数,然后从另一个线程调用它——搞定!
请注意auth.hashPassword()
,无论最初是否返回承诺,都会hashPassword
返回一个承诺 - 由于工作者通信的异步特性,返回值将被承诺化。
那么错误处理呢?这很简单,因为我们现在使用的是基于 Promise 的 API。
// master.js
import { spawn, Thread, Worker } from "threads"
async function main() {
let auth, hashed
try {
auth = await spawn(new Worker("./workers/auth"))
} catch (error) {
// Cannot spawn the worker or crashed immediately before doing anything
}
try {
hashed = await auth.hashPassword("Super secret password", "1234")
} catch (error) {
// Hashing this password failed
}
console.log("Hashed password:", hashed)
await Thread.terminate(auth)
}
main().catch(console.error)
顺便问一下,你注意到了吗Thread.terminate()
?我们使用它来终止一个工作进程。
在 node.js 中运行
现在,让我们将之前的示例代码中的 ES 模块import
语句改为调用。你可以从这个 GitHub Gistrequire()
克隆代码。
$ git clone git@gist.github.com:925395687f42f6da04d111adf7d428ac.git ./threads-gist
$ cd threads-gist
$ npm install
运行它很简单。
$ node ./master
此代码将在任何带有工作线程支持的 node.js 版本中运行,因此 node 12+ 或 node 10+ 具有功能标志设置。
您甚至可以在 Node 8.12+ 上运行它。安装tiny-worker
npm 包 - 如果工作线程不可用,threads.js 会自动将其作为 polyfill 加载。
使用 webpack 构建
很多人使用 webpack 打包代码以进行前端部署。那么,现在该如何使用 webpack 构建这些代码呢?
我们按原样使用我们的代码,采用我们的 webpack 配置并添加threads-plugin
- 就是这样!
// webpack.config.js
const path = require("path")
+ const ThreadsPlugin = require("threads-plugin")
module.exports = {
entry: {
app: "./src/index.js"
},
mode: "development",
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
},
{
test: /\.jsx?$/,
use: ["babel-loader"]
}
]
},
output: {
path: path.join(__dirname, "dist")
},
plugins: [
new HtmlPlugin(),
+ new ThreadsPlugin()
]
}
该插件基于 Google 的worker-plugin
- 它将识别new Worker()
表达式,确保引用的工作文件独立于主入口点捆绑,并将表达式中的路径重写new Worker()
为工作包路径。
一流的 TypeScript 支持
Threads.js 是用 TypeScript 编写的,因此完全是静态类型的,因此 IDE 的 IntelliSense 会在您编写时显示所有可用的导出、函数和参数,并附带文档。不仅如此,运行 TypeScript Worker 也变得更加轻松。
在 node.js 中运行 TypeScript 代码时,您会经常发现自己ts-node
在开发中使用并在生产中运行转换后的 JavaScript 代码。
在解析 Worker 时,threads.js 会尝试加载已转译的 JavaScript Worker。如果失败且ts-node
已安装,它将自动进行故障转移,使用 运行未转译的 TypeScript Worker 文件ts-node
。你无需费力 🙌
线程池、可观察对象等
还有更多值得探索!
- 线程池用于生成多个工作线程并向其分配任务
- 返回可观察对象以公开要订阅的事件
- 支持可传输对象以高效传递二进制数据
- 以及更多…🚀
您可以在threads.js.org上找到详细文档。
未来还会有更多功能。您可以查看GitHub 仓库及其问题,了解当前正在讨论的内容,或者关注仓库的发布情况,了解最新动态。
今天就到这里——希望你喜欢这篇博文。如果你喜欢这个项目,请在 GitHub 上给代码库点个赞,为开发做出贡献,或者成为赞助商。
欢迎在下面发表评论并留下任何类型的反馈。
节日快乐,黑客攻击愉快!
安迪
预告图片由 Adi Goldstein 在 Unsplash 上发布。
文章来源:https://dev.to/andywer/seamless-web-workers-worker-threads-threads-js-2g36