Skip to content

多進程 Worker

對於遊戲來說,每幀 16ms 是極其寶貴的,如果有一些可以非同步處理的任務,可以放置於 Worker 中運行,待運行結束後,再把結果返回到主執行緒。

Worker 運行於一個單獨的全域上下文與執行緒中,不能直接呼叫主執行緒的方法。

Worker 與主執行緒之間的資料傳輸,雙方使用Worker.postMessage()來發送數據,Worker.onMessage()來接收數據,傳輸的數據並不是直接共享,而是被複製的。

使用流程

步驟1. 設定 Worker 訊息

在 game.json 中可配置 Worker 程式碼放置的目錄,目錄下的所有 JS 程式碼最終將被打包成一個 JS 檔案:

js
{
  "workers": "workers"
}

透過上述方式配置,workers 目錄下的所有 JS 文件會被打包為一個 JS 文件,並作為小遊戲首包的一部分。

小遊戲首包體積是有上限的(目前為4M),為了使 worker 程式碼不佔用首包體積,從基礎庫 v2.0.10 開始支援將 worker 程式碼打包為一個分包。 (需更新開發者工具至最新版本)

worker 程式碼配置為分包範例:

js
{
  "workers": {
    "path": "workers",
    "isSubpackage": true // true means the Worker is packaged as a subpackage. Default is false. Setting false is equivalent to { "workers": "workers" }
  }
}

步驟2. 新增 Worker 程式碼文件

根據步驟1中的配置,在程式碼目錄下新建以下兩個入口檔案:

js
workers / request / index.js;
workers / request / utils.js;
workers / response / index.js;

添加後,目錄結構如下:

js
├── game.js
├── game.json
├── project.config.json
└── workers
    ├── request
    │   ├── index.js
    │   └── utils.js
    └── response
        └── index.js

步驟3. 編寫 Worker 程式碼

在workers/request/index.js編寫Worker響應代碼

js
const utils = require("./utils");
// In the Worker thread execution context, a global worker object is exposed. Use worker.onMessage/postMessage directly
worker.onMessage(function (res) {
  console.log(res);
});

步驟4. 在主執行緒中初始化 Worker

在主執行緒的程式碼 game.js 中初始化 Worker。

js
const worker = wx.createWorker("workers/request/index.js"); // Specify the Worker entry file path, absolute path

從基礎函式庫 v2.0.10 開始,如果 worker 程式碼配置為了分包,則需要先透過 wx.preDownloadSubpackage 介面下載好 worker 程式碼,再初始化 Worker:

js
var task = wx.preDownloadSubpackage({
  packageType: "workers",
  success(res) {
    console.log("load worker success", res);
    var worker = wx.createWorker("workers/request/index.js"); // Create Worker If the Worker subpackage is not fully downloaded, calling createWorker will result in an error
  },
  fail(res) {
    console.log("load worker fail", res);
  },
});

task.onProgressUpdate((res) => {
  console.log(res.progress); // Monitor download progress using onProgressUpdate
  console.log(res.totalBytesWritten);
  console.log(res.totalBytesExpectedToWrite);
});

步驟5. 主執行緒向 Worker 發送訊息

js
worker.postMessage({
  msg: 'hello worker'
})

worker 對象的其它介面請查看worker接口说明

注意事項

  • Worker 最大並發數量限制為 1 個,建立下一個前請用 Worker.terminate()結束當前 Worker;
  • Worker 內程式碼只能 require 指定 Worker 路徑內的文件,無法引用其它路徑;
  • Worker 的入口檔案由wx.createWorker()時指定,開發者可動態指定 Worker 入口文件;
  • Worker 內不支援 wx 系列的 API;
  • Workers 之間不支援發送訊息;
  • Worker 目錄內只支援放置 JS 文件,其他類型的靜態文件需要放在 Worker 目錄外。