Web Worker 是什么? 可以用在哪?
2026年1月6日
在早期的前端开发,会放在前端处理的东西不多,基本上不脱离简单的事件操作、动画特效;不过随着前端发展越来越纯熟,开发者在前端做的事情越来越多,当初 JavaScript 的设计就逐渐不足以支应新的需求。
这时前端社群逐渐有了不同的技术,来弥补 JavaScript 做不到的,藉此让开发者们能在前端做更复杂的操作;在前端开发很常听到的 Web Worker 与 Service Worker 都在这个范畴中。
Web Worker 是什么?
Web Worker 的核心概念是开启另一个执行绪做背景运算,让复杂运算不会阻塞 JavaScript 的主要执行绪。
要理解这点,需要从历史的脉络来看 JavaScript 的发展。最开始 JavaScript 被设计时,那个年代的电脑与浏览器,都远不如现代的强大,所以把 JavaScript 设计成单一执行绪 (single-threaded),每次只能做一件事,基本上没什么问题。
但是现代浏览器能够多工,前端开发者可以让浏览器同时处理不同的事情,在这个脉络下,JavaScript 的单一执行绪设计,就变成某种阻碍,无法有效发挥现代浏览器多核 CPU 的运算能力。
具体来说,假如今天有某个比较复杂的运算在跑,其他事情就没办法同时被处理;从前端的角度来看,这代表对使用者来说,画面可能会卡住不动,使用体验相当不理想。但明明浏览器能够做更多事,所以如果能有一个机制让复杂的、会卡住 JavaScript 执行绪的那些任务被分担处理,就能解决这种不理想的使用者体验。
Web Worker 的存在就是在解决这个问题。我们可以透过浏览器的 Web Worker API,去另一个执行绪 (在社群很多人称之为 Worker Thread) 执行任务;这对 JavaScript 所在的执行绪来说,等同于在背景有另一个帮手帮忙执行任务,所以不会因为要处理运算,就被迫卡着不能做其他事。
可以在这张图看到,透过 Web Worker,假如今天有某个需要花比较多时间的运算,就先透过 postMessage 放到 Worker 的执行绪做运算;运算完拿到结果后,再传回主要执行绪,以平行的方式进行处理,这样就能不阻塞主要执行绪。
Web Worker 的具体使用情境
在谈具体的 Web Worker 使用情境时,推荐读者不要硬背下这些使用情境,而是回到脉络来思考。Web Worker 的出现是要解决前端复杂运算阻塞主要执行绪,导致画面卡住的不良使用体验。
进一步说,使用者做了某个操作,会希望立即得到 UI 的回馈,假如某件事情会导致这种立即回馈无法马上发生,就可以思考使用 Web Worker,来把卡住的运算,搬到另一个执行绪来处理。
一个常见的使用情境,是在许多图片管理网站 (例如 Flickr 或 Google Photos),在载入图片时,会同时去解析图片拿到图片的元资料 (meta-data),在这个过程会需要把图片转成 ArrayBuffer 的格式,所以需要花时间做运算;这就是能用上 Web Worker 的情境,在 Worker 执行绪处理完后,再把拿到的元资料传回主要执行绪,就能避免主执行绪阻塞。
特别注意,Web Worker 这种开另一个执行绪处理运算的做法,直观看起来能让效能变好,但并非所有情境都是如此。往下读之前,推荐读者可以稍微暂停,思考一下多开一个执行绪的取舍。
在使用 Web Worker 时,一个显而易见的成本是传递讯息的成本,以上面提过的这张图来说,把要处理的东西从主要执行绪,传给 Worker 执行绪,处理完后再传回主要执行绪,这每一个步骤虽然不需要花太多时间,但仍是额外的成本。所以假如某个运算,其实很快就能处理完,特别是那种对使用者体验影响不大的运算,其实可以在主要执行绪处理即可,无需额外丢到 Worker 执行绪处理。
进一步说,加快主要执行绪处理,除了 Web Worker 这个思考角度外,还有其他可以做的方式。例如目前社群中热门的做法之一,是透过 WebAssembly 把耗时的运算转由其他语言处理 (例如 Rust),在某些场景下,这会比用 Web Worker 来得更快。
阅读更多
如果你想了解 Web Worker 如何具体使用,以及 Service Worker 与 Web Worker 的区别,我们在 E+ 的主题文中有更详细的讨论。感兴趣的读者,欢迎加入 E+ 后阅读 (连结)。