JavaScript 语言采用的是单线程模型,也就是说,所有任务只能在一个线程上完成,一次只能做一件事。前面的任务没做完,后面的任务只能等着。随着电脑计算能力的增强,尤其是多核 CPU 的出现,单线程带来很大的不便,无法充分发挥计算机的计算能力。
Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。
Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。
一些异步处理的任务,可以放置于 Worker 中运行,待运行结束后,再把结果返回到小程序主线程。Worker 运行于一个单独的全局上下文与线程中,不能直接调用主线程的方法。
Worker 与主线程之间的数据传输,双方使用Worker.postMessage()
来发送数据,Worker.onMessage()
来接收数据,传输的数据并不是直接共享,而是被复制的。
在 app.json 中可配置 Worker 代码放置的目录,目录下的代码将被打包成一个文件:
配置示例:
{
“workers”: “workers”
}
根据步骤 1 中的配置,在代码目录下新建以下两个入口文件:
workers/request/index.js
workers/request/utils.js
workers/response/index.js
添加后,目录结构如下:
├── app.js
├── app.json
├── project.config.json
└── workers
├── request
│ ├── index.js
│ └── utils.js
└── response
└── index.js
在 workers/request/index.js
编写 Worker 响应代码
const utils = require('./utils')
// 在 Worker 线程执行上下文会全局暴露一个 worker 对象,直接调用 worker.onMeesage/postMessage 即可
worker.onMessage(function (res) {
console.log(res)
})
在主线程的代码 app.js 中初始化 Worker
const worker = wx.createWorker(‘workers/request/index.js’) // 文件名指定 worker 的入口文件路径,绝对路径
worker.postMessage({
msg: ‘hello worker’
})
注意事项
创建一个 Worker 线程。目前限制最多只能创建一个 Worker,创建下一个 Worker 前请先调用 Worker.terminate
string scriptPath worker 入口文件的绝对路径
返回值
Worker 对象
Worker 实例,主线程中可通过 wx.createWorker 接口获取,worker 线程中可通过全局变量 worker 获取。
Worker.postMessage(Object message)
向主线程/Worker 线程发送的消息。
function callback
主线程/Worker 线程向当前线程发送的消息的事件的回调函数
参数 Object res
Worker.terminate()
结束当前 Worker 线程。仅限在主线程 worker 对象上调用。
示例代码
运行以下代码需先进行基础配置,详细请查阅 多线程 文档了解基础知识和配置方法。
const worker = wx.createWorker('workers/request/index.js') // 文件名指定 worker 的入口文件路径,绝对路径
worker.onMessage(function (res) {
console.log(res)
})
worker.postMessage({
msg: 'hello worker'
})
worker.terminate()
Worker.onMessage(function callback)
监听主线程/Worker 线程向当前线程发送的消息的事件。
Object message
需要发送的消息,必须是一个可序列化的 JavaScript key-value 形式的对象。
示例代码
worker 线程中
worker.postMessage({
msg: 'hello from worker'
})
主线程中
const worker = wx.createWorker('workers/request/index.js')
worker.postMessage({
msg: 'hello from main'
})
workers/request/index.js
const utils = require('./utils')
console.log('hello worker')
worker.postMessage({
msg: 'hello from worker: ' + utils.test(),
buffer: utils.str2ab('hello arrayBuffer from worker')
})
worker.onMessage((msg) => {
console.log('[Worker] on appservice message', msg)
const buffer = msg.buffer
console.log('[Worker] on appservice buffer length ', buffer)
console.log('[Worker] on appservice buffer', utils.ab2str(buffer))
})
workers/request/utils.js
function test() {
return 1 + 1
}
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint16Array(buf));
}
function str2ab(str) {
var buf = new ArrayBuffer(str.length * 2); // 2 bytes for each char
var bufView = new Uint16Array(buf);
for (var i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
module.exports = {
test: test,
ab2str: ab2str,
str2ab: str2ab
}