运行
Run 是一个小型库,可以在 Web Worker 中运行用户提供的代码。 其主要目的是通过代码片段实现数据转换,因此某些全局功能被禁用。
该库接收一段 JavaScript 代码(以字符串形式)和一个数据载荷,并返回其执行结果。
它尽可能安全地运行"不受信任"的代码,因为:
- Web Worker 无法访问 DOM
- Web Worker 无法访问主应用程序的域上下文
- Web Worker 在单独的线程中运行,不会阻塞 UI
- Web Worker 不应能进行网络操作(仍在调查中)
主要用例是在低代码应用程序中,用户可以运行代码片段(不一定由同一用户创建)来完成各种任务。
Run 将在我们即将推出的开源仪表板 SDK 项目 Slashd 中使用。
这里有一个小型沙盒应用 here 供您试用。
安装
使用 UnPkg CDN:
<script src="https://unpkg.com/@slashd/run"></script>
使用 SkyPack CDN:
<script type="module">
import SlashdRun from 'https://cdn.skypack.dev/@slashd/run'
// 你的代码
</script>
使用包管理器:
npm install @slashd/run
然后,在浏览器中引入:
<script src="node_modules/@slashd/run/dist/slashd-run.min.js"></script>
或在使用打包工具的模块中通过 ES6 引入:
import SlashdRun from '@slashd/run'
如何使用
您可以创建一个或多个任务(独立的 worker):
import SlashdRun from '@slashd/run'
const task = new SlashdRun()
exe
方法返回一个 promise,因此您可以使用 await
:
const myCode = `return Math.random() * param`
const res = await task.exe(myCode, {param:20})
// res 可能是 12.345657676
您可以通过以下方式捕获代码错误:
const myCode = `return MathRandom * param`
try{
const res = await task.exe(myCode, {param:20})
}catch(e){
console.log(e)
}
// ReferenceError: MathRandom is not defined
感谢 @rob-gordon,您可以使用异步代码:
const myCode = `return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(Math.random())
}, 2000)
})`
const res = await task.exe(myCode, {param:20})
// res 可能是 12.345657676
或者,使用 restrict:false
选项:
const myCode = `return await fetch('https://jsonplaceholder.typicode.com/todos').then(res => res.json())`
const res = await task.exe(myCode, {param:20})
// 200 [{...}, ...]
配置
您可以通过在设置中添加 deps
属性作为外部路径数组,指定在 worker 中加载外部库:
const task = new SlashdRun({deps:['https://unpkg.com/lodash', 'https://www.example.com/mylibrary.js']})
使用上述设置,可以在提供的代码中使用 lodash
:
const myCode = `_.difference(arr1, arr2);`
const res = await task.exe(myCode, {arr1:[2, 1], arr2:[2, 3]})
// => [1]
默认情况下,该库尝试阻止 Web Worker 的某些功能,如网络函数。
如果您想禁用此行为并保留所有标准 Web Worker 功能,请添加 restrict
属性并将其设置为 false
:
const task = new SlashdRun({restrict:false})
使用此选项,用户提供的代码可以进行网络操作,如 fetch()
。
您还可以使用特定的 init
静态方法全局配置库。这样,所有任务都将使用相同的设置:
import { init } from '@slashd/run'
init({deps:['https://unpkg.com/lodash'], restrict:false})
要终止 worker,您可以使用:
task.destroy()
使用 worker 池
如果您需要从预定义的可用 worker 池中获取任务(以限制 worker 的创建),可以使用这个静态方法代替 new SlashdRun
方式:
import { init, getFromPool } from '@slashd/run'
init({maxWorkers:3}) // 必需!
const task = getFromPool()
在这种情况下,库配置需要使用 init
方法完成。此外,maxWorkers
是必需的,且必须至少为 1
或更大。请注意,浏览器对可以运行的并发 worker 数量有硬性限制。根据我们的经验,3/4 是一个较好的安全最大数量。通常,一个 worker 就足够了。
要释放池及其 worker,请使用以下方法:
import { disposePool } from '@slashd/run'
disposePool()
贡献
安装依赖:
npm i
启动监视器:
npm start