JavaScript 中 Promise 怎么实现 WebWorker 任务派发

风静姑娘_5934

风静姑娘_5934

2026-09-15

465人浏览

原创

promise 本身不能直接实现 webworker 任务派发,但可通过 postmessage + 唯一 id + map 缓存 resolve/reject 封装成可 await 的函数,使 worker 调用无缝融入 async/await 流程。

javascript 中 promise 怎么实现 webworker 任务派发

Promise 本身不能直接“实现” WebWorker 任务派发,但它可以和 WebWorker 配合,封装异步通信逻辑,让 Worker 调用像调用普通函数一样返回 Promise,从而自然融入 async/await 流程。

核心思路:用 MessageChannel 或 postMessage + Promise 封装通信

WebWorker 是独立线程,主线程与 Worker 之间只能通过 postMessage 异步通信。Promise 的作用是把这种“发送 → 等待响应 → 处理结果”的流程包装成可 await 的形式。

  • 每次任务派发时,生成唯一 ID(如递增序号或 Symbol),并用该 ID 关联一个 resolve/reject 函数
  • 将任务数据连同 ID 一起 post 到 Worker
  • Worker 执行完后,把结果(含相同 ID)发回主线程
  • 主线程收到响应后,根据 ID 查找并调用对应的 resolve 或 reject

简易封装示例(主线程)

以下是一个轻量、无依赖的封装方式:

const worker = new Worker('./task-worker.js');

const pending = new Map();
let id = 0;

Java Development Manual
Java Development Manual

Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...

下载

worker.onmessage = ({ data }) => {
  const { msgId, result, error } = data;
  const handler = pending.get(msgId);
  if (handler) {
    pending.delete(msgId);
    if (error) handler.reject(new Error(error));
    else handler.resolve(result);
  }
};

function runInWorker(task, payload) {
  return new Promise((resolve, reject) => {
    const msgId = ++id;
    pending.set(msgId, { resolve, reject });
    worker.postMessage({ msgId, task, payload });
  });
}

之后就可以这样使用:

async function doHeavyWork() {
  try {
    const result = await runInWorker('sortArray', [5, 2, 9, 1]);
    console.log('Sorted:', result); // [1, 2, 5, 9]
  } catch (e) {
    console.error('Worker failed:', e);
  }
}

Worker 端需配合响应(task-worker.js)

Worker 不需要 Promise,只需监听任务、执行、再 post 回带 msgId 的结果:

const handlers = {
  sortArray: (arr) => [...arr].sort((a, b) => a - b),
  fibonacci: (n) => {
    let a = 0, b = 1;
    while (n-- > 1) [a, b] = [b, a + b];
    return b;
  },
};

self.onmessage = ({ data }) => {
  const { msgId, task, payload } = data;
  try {
    const result = handlers[task]?.(payload);
    self.postMessage({ msgId, result });
  } catch (err) {
    self.postMessage({ msgId, error: err.message });
  }
};

进阶建议:用 MessageChannel 实现更健壮的双向通道

如果 Worker 需要频繁通信或支持流式响应(如分块处理),推荐用 MessageChannel 创建独立端口,避免 onmessage 冲突:

  • 主线程创建 const { port1, port2 } = new MessageChannel()
  • port2 传给 Worker:worker.postMessage({ type: 'init', port: port2 }, [port2])
  • Worker 接收后调用 port.start(),之后只通过该 port 收发
  • 主线程在 port1.onmessage 中处理响应,同样用 ID 匹配 Promise

这种方式隔离性更好,适合复杂 Worker 场景,也便于后续扩展取消机制(AbortSignal)或超时控制。

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
js获取数组长度的方法
js获取数组长度的方法

在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

2023.06.20

4086

5

js刷新当前页面
js刷新当前页面

js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

2023.07.04

1049

3

js四舍五入
js四舍五入

js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

2023.07.04

3964

6

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

2023.09.01

820

4

JavaScript转义字符
JavaScript转义字符

JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.04

1716

5

js生成随机数的方法
js生成随机数的方法

js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

2023.09.04

2985

4

如何启用JavaScript
如何启用JavaScript

JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

2023.09.12

3893

6

Js中Symbol类详解
Js中Symbol类详解

javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

2023.09.20

2480

5

java访问控制修饰符介绍
java访问控制修饰符介绍

java访问控制修饰符有四种,分别是public、protected、private、默认访问修饰符。详细介绍:1、public,public是最宽松的访问控制修饰符,被修饰的类、方法和变量可以被任何其他类访问,当一个类、方法或变量被声明为public时,它们可以在任何地方被访问,无论是同一个包中的类还是不同包中的类;2、protected修饰符等等。

2023.09.20

808

7

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WebStorm 官方调试文档
WebStorm 官方调试文档

共0课时 | 0人学习

React 教程
React 教程

共58课时 | 11.9万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 6.5万人学习