You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Web Worker打开WebSerialAPI选中的SerialPort?

解决Web Serial API中无法将SerialPort传递给Web Worker的问题

方案1:使用SerialPort.for()传递权限令牌(推荐)

这是Web Serial API官方支持的跨上下文传递端口的方法,通过生成可序列化的权限令牌,让Worker获取对应的端口实例:

主线程代码:

// 主线程:用户选择串口后生成权限令牌并发送给Worker
let port = await navigator.serial.requestPort();
// 请求用于指定Worker的端口权限令牌
const portToken = await port.for(serialportWorker);
// 将令牌发送给Worker
serialportWorker.postMessage({
  type: "open-port",
  token: portToken
});

Web Worker代码:

// Web Worker:通过令牌获取端口并处理串口流
self.onmessage = async (event) => {
  if (event.data.type === "open-port") {
    try {
      // 用令牌获取对应的SerialPort实例
      const port = await navigator.serial.getPort(event.data.token);
      if (!port) {
        console.error("无法通过令牌获取指定串口");
        return;
      }

      // 打开串口(根据你的设备配置波特率等参数)
      await port.open({ baudRate: 9600 });
      
      // 开始读取串口数据
      const reader = port.readable.getReader();
      while (true) {
        const { value, done } = await reader.read();
        if (done) {
          reader.releaseLock();
          break;
        }
        // 处理数据,可将结果发回主线程
        self.postMessage({
          type: "serial-data",
          data: value
        });
      }
    } catch (err) {
      console.error("串口操作出错:", err);
    }
  }
};

原理:SerialPort.for()方法会生成一个可被结构化克隆的令牌,Worker通过navigator.serial.getPort()传入令牌即可获取对应的端口实例,完全避免了直接传递无法克隆的SerialPort对象的问题。

方案2:主线程转发串口数据到Worker(兼容 fallback)

如果目标浏览器不支持SerialPort.for()方法,可以让主线程仅负责打开串口和转发原始数据,将数据处理逻辑放在Worker中,最小化主线程的工作量:

主线程代码:

// 主线程:打开串口并转发数据到Worker
let port = await navigator.serial.requestPort();
await port.open({ baudRate: 9600 });
const reader = port.readable.getReader();

// 持续读取串口数据并转发给Worker
(async function forwardSerialData() {
  while (true) {
    const { value, done } = await reader.read();
    if (done) {
      reader.releaseLock();
      break;
    }
    // 仅转发原始数据,不做复杂处理
    serialportWorker.postMessage({
      type: "raw-data",
      data: value
    }, [value.buffer]); // 用Transferable Objects优化数据传递性能
  }
})();

Web Worker代码:

// Web Worker:处理串口数据
self.onmessage = (event) => {
  if (event.data.type === "raw-data") {
    // 在这里处理高吞吐量的串口数据,不会阻塞主线程
    const processedData = handleSerialData(event.data.data);
    // 可选:将处理结果发回主线程
    self.postMessage({
      type: "processed-data",
      result: processedData
    });
  }
};

function handleSerialData(rawData) {
  // 实现你的数据解析逻辑,比如GPS数据解析
  // ...
}

注意:使用Transferable Objects(代码中的[value.buffer])可以避免数据拷贝,提升大吞吐量数据的传递性能。


内容的提问来源于stack exchange,提问作者Patryk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 01:52:48