强型闯入DenoLand[25] - 使用 Deno 打造多线程应用(2)

Node.js之父新专案Deno 1.0正式亮相| iThome

强型闯入DenoLand[25] - 使用 Deno 打造多线程应用(2)

在了解何谓多线程以後,我们来看看要如何在 Deno 开发多线程的程序吧!

Deno 支援 Web Worker API , Workers 可以让程序运作在多个线程上,而每一个 Worker 实体都在独立的线程上运作。

目前为止,Deno 只支持 module 类型的 Worker 。因此,在初始化新的 Worker 实体时需要加入 type option :

new Worker(new URL("worker.js", import.meta.url).href, { type: "module" });

需要注意的是: Deno 目前不支持相对模块说明符 。使用者可以改用 URL 构造器并使用 import.meta.url 引入本地端的程序码。

// Good
new Worker(new URL("worker.js", import.meta.url).href, { type: "module" });

// Bad
new Worker(new URL("worker.js", import.meta.url).href);
new Worker(new URL("worker.js", import.meta.url).href, { type: "classic" });
new Worker("./worker.js", { type: "module" });

举例来说,有一个主程序码 main.ts 以来用来派发的工作程序码 worker.ts

// main.ts
new Worker(new URL("worker.ts", import.meta.url).href, { type: "module" });
// worker.ts
console.log("hello world");
self.close();

因为执行 main.ts 时会有读取 worker.ts 的动作,所以要记得加入 --allow-read 标签:

deno run --allow-read main.ts

载入远端模组

现在,让我们来尝试将 worker.ts 移动到远端上:

// main.ts
new Worker("https://example.com/worker.ts", { type: "module" });

因为有网路存取需求,执行时需要加入 --allow-net

deno run --allow-net main.ts

将脚本发布到 gist

Github 有提供 gist 服务,让开发者可以张贴自己的程序码,方便分享或是用於撰写技术文章。

笔者尝试将程序码丢到 gist 上:

// main.ts
new Worker("https://gist.githubusercontent.com/ianchen0119/5935736ab973fcbcbbbb5294d8bd2655/raw/a94a6547d8b66f50441f4cef8a5218ab19b49c11/worker.ts", { type: "module" });

gist 上的程序码:

await console.log("hello world");
self.close();

执行时同样需要加入 --allow-read 标签唷!

眼尖的读者应该有发现该范例在 console.log("hello world"); 前面多了一个 await

可以参考 Link

传递参数

Workers 也可以让我们将需要的参数传入要派发的任务( Worker.ts )当中:

// main.js
const worker = new Worker(new URL("worker.js", import.meta.url).href, { type: "module" });
worker.postMessage('Hello World!');
// worker.js
self.onmessage = async (e) => {
	let { data } = e;
	console.log(data);
	self.close();
  };

在 worker 中使用 Deno

一般情况下,命名空间 Deno 在 Worker 范围内是不可用的。

不过我们可以利用 deno: true 选项做到这点:

// main.js
const worker = new Worker(new URL("worker.js", import.meta.url).href, {  type: "module",  deno: true,});
worker.postMessage({ filename: "./log.txt" });
// worker.js
self.onmessage = async (e) => {
  const { filename } = e.data;  
  const text = await Deno.readTextFile(filename);  
  console.log(text);  
  self.close();
};

由於该功能还不稳定,执行时需要加入 --unstable 旗标:

$ deno run --allow-read --unstable main.js

补充:当 Deno 命名空间在 Worker 作用域中可用时,将会继承 main.js 的权限(使用--allow-*标志指定的权限)。

10/22 更新: 多线程在 Deno 上有任何限制吗?

笔者在 Deno 的 Github Repo 上公开发问了关於多执行绪的问题,主要提到 Deno 是否有限制执行绪的数量以及每条执行绪是否有记忆体限制, Deno 的主要贡献者回答:

There are no limits, you can create as many as you want
Again, there are no limits. We now have facilities to set heap limits on the isolate, but it's not possible to set them for workers.

在这边提供给有需要的读者做参考。

总结

今天介绍了 Workers 的基本用法,明天的教学就会以这个基础去做简单的应用,敬请期待。

BTW: Deno v1.4.6 已经发布了,有兴趣的读者可以上去看看这次又更新了哪些东西唷!

延伸阅读

同样的事情在不同人眼中可能会有不同的见解、看法。

在读完本篇以後,笔者也强烈建议大家去看看以下文章,或许会对型别、变数宣告...等观念有更深层的看法唷!


<<:  [Day 27] 所以说那个手机版

>>:  从零开始-30日练习开发iOS APP-UserDefault Day-28

Day 23. Server Side Rendering

Server side rendering 在一般的 Vue 专案里可能会有一个App.vue,里面...

Day30 换脸效果 ( 你全家都同一张脸 )

换脸效果 ( 你全家都同一张脸 ) 教学原文参考:换脸效果 ( 同一张脸 ) 这篇文章会介绍使用 G...

[Day3]什麽是比特币?

hi!今天的主题是比特币!会分成五个部分做介绍,有定义、起源、特性、交易、比较,如果对比特币有兴趣...

Day 30: 完赛总结

终於完赛啦! 这次挑战赛仅聚焦於结构化资料的资料分析,非结构化资料(图片声音影片等等),就需要用到深...

【Docker图解教学】Kubernetes & Docker的分手肥皂剧

Youtube连结:https://bit.ly/2MbU9cR 前阵子在社群广为流传的议题「轰都...