uni-app App端不支持Web Worker,仅可通过plus.threads实现类多线程,但仅限app-plus且需手动管理线程生命周期与通信,Worker内不可用uni/Vue/模块系统,复杂任务建议原生插件。

uni-app App端Worker支持现状
uni-app 的 Worker 在 App 端(iOS/Android)**不原生支持 Web Worker API**,直接调用 new Worker() 会报错 Worker is not defined 或白屏。这是最常踩的坑——开发者按 H5 写法迁移后,在真机调试时突然失效。
原因很实在:App 端 WebView(如 iOS WKWebView、Android X5)虽支持 Web Worker,但 uni-app 的 App 编译层(基于 Vue 2/3 + 原生渲染桥接)并未将主线程与 Worker 线程的通信通道打通,也未提供 JS 线程隔离能力。
- 仅 H5 平台能用标准
Worker,且需注意构建时保留.worker.js文件不被 Uglify - 小程序平台(微信、支付宝等)有自己的
Worker实现,但路径、生命周期、API 均与 Web 不同,不可复用 - App 端真正可用的“类多线程”方案只有
native plugin或plus.threads(仅 5+ App 引擎支持)
plus.threads 是 App 端唯一可行的轻量级线程方案
plus.threads 是 DCloud 官方在 5+ Runtime 中提供的原生线程封装,它不是 Web Worker,但能实现 JS 代码在独立线程中运行,适合 CPU 密集型任务(如 Base64 编码、JSON 解析、加密计算)。
关键限制:只在 app-plus 编译目标下有效,且必须使用 5+ 引擎(即非 weex 模式),H5 和小程序完全不可用。
- 创建线程用
plus.thread.create(),传入 JS 字符串或本地.js路径(推荐后者,便于调试) - 线程内不能访问
document、window、uni等全局对象,只能用plus提供的有限 API(如plus.runtime.quit()) - 主线程与子线程通过
postMessage/onmessage通信,消息体必须是可序列化的纯对象,不能传函数、DOM 节点或undefined - 线程执行完不会自动销毁,需手动调用
thread.quit(),否则持续占用内存
const thread = plus.thread.create('_www/js/calc.worker.js');
thread.postMessage({ data: [1, 2, 3, 4, 5] });
thread.onmessage = (e) => {
console.log('结果:', e.data);
};
// 别忘了退出
thread.quit();
Worker 文件里不能写 uni 相关逻辑
所有放在 .worker.js(或线程加载的 JS 文件)里的代码,运行环境是纯净的 JS 上下文,uni、Vue、require、import(ESM)、console(部分平台无输出)全都不生效。
常见错误是把业务工具函数直接挪过去,结果发现 uni.getSystemInfoSync 报错,或 require('@/utils/crypto.js') 找不到模块——因为线程里没有模块系统,也没有 uni 的运行时注入。
- 只能用原生 JS:
Array.prototype.map、atob、JSON.parse、Uint8Array等 - 加密类操作建议用
crypto-js的 UMD 版本(打包进单文件),避免动态require - 路径必须是相对
_www根目录的绝对路径,如'_www/js/sha256.min.js',不能用@/别名 - 调试靠
plus.runtime.consoleLog(仅 Android 可见)或主线程postMessage回传日志
替代方案:把重计算下沉到原生插件更稳定
如果任务复杂度高(比如图像处理、音视频解码、大数组排序),plus.threads 仍可能卡顿或崩溃——JS 线程在 5+ 引擎里本质还是 V8/JavaScriptCore 的协程模拟,并非 OS 级线程。
这时更靠谱的做法是写一个原生插件(Android/iOS),暴露简单接口给 JS 调用,把耗时逻辑彻底交给原生。虽然开发成本高一点,但性能、稳定性、兼容性都远超 JS 线程。
- 插件接口设计要极简:输入参数尽量扁平(字符串、数字、base64),返回值同理
- 避免在插件里做 UI 操作或回调大量 JS 函数,防止 JS 主线程阻塞
- uni-app 官方插件市场已有部分通用计算插件(如
zlib-unzip、base64-encode),可先搜再造轮子 - 插件调试周期长,建议先用
plus.threads验证逻辑,再逐步迁移到原生
真正麻烦的从来不是“怎么开个线程”,而是线程间数据怎么安全传、错误怎么捕获、内存怎么清理——这些细节没处理好,开十个线程也救不了卡顿。










