通过AngularJS调用Chrome WebUSB API连接热敏打印机遇问题求助
我来帮你搞定AngularJS里调用WebUSB连接ESC/POS热敏打印机的问题!下面是适配AngularJS生态的完整解决方案,把原生JS的逻辑转化为符合AngularJS MVVM模式的实现:
在AngularJS中实现WebUSB API连接ESC/POS打印机
核心思路
AngularJS的核心是分离业务逻辑与DOM操作,所以我们会把WebUSB相关的设备处理逻辑封装成可复用的服务,再在控制器里调用服务,用AngularJS的数据绑定来管理按钮状态,彻底告别原生JS直接操作DOM的写法。
步骤1:封装WebUSB打印机服务
先创建一个专门的服务,把设备查找、连接、通信的逻辑都放这里,方便后续在多个控制器里复用:
angular.module('yourAppModule') // 替换成你的项目模块名 .service('UsbPrinterService', function() { // 替换成你的打印机厂商ID和产品ID(十六进制格式) const VENDOR_ID = 0xXXXX; const PRODUCT_ID = 0xXXXX; // 获取已连接的打印机设备 this.getConnectedDevices = async function() { try { return await navigator.usb.getDevices({ filters: [{ vendorId: VENDOR_ID, productId: PRODUCT_ID }] }); } catch (error) { console.error('获取已连接设备失败:', error); throw error; } }; // 请求用户选择打印机(弹出设备选择框) this.requestDevice = async function() { try { return await navigator.usb.requestDevice({ filters: [{ vendorId: VENDOR_ID, productId: PRODUCT_ID }] }); } catch (error) { console.error('请求设备连接失败:', error); throw error; } }; // 打开设备并配置接口(ESC/POS打印机通用配置) this.openDevice = async function(device) { try { await device.open(); await device.selectConfiguration(1); // 大多数打印机用配置1 await device.claimInterface(0); // 大多数打印机用接口0 return device; } catch (error) { console.error('打开设备失败:', error); throw error; } }; // 发送ESC/POS打印指令(扩展功能) this.sendPrintData = async function(device, printData) { try { // 输出端点通常为0x01,输入端点为0x81,可根据打印机说明书调整 await device.transferOut(0x01, printData); console.log("打印数据发送成功"); } catch (error) { console.error('发送打印数据失败:', error); throw error; } }; });
步骤2:在控制器中调用服务
接下来在控制器里注入服务,处理按钮点击事件,用$scope管理连接状态,完全用AngularJS的数据绑定替代原生DOM操作:
<!-- 你的页面视图 --> <div ng-controller="PrinterController"> <button ng-click="connectPrinter()" ng-disabled="isConnecting" > {{ isConnected ? '已连接打印机' : '连接打印机' }} </button> <!-- 可选:打印测试按钮 --> <button ng-click="printTest()" ng-disabled="!isConnected" style="margin-left:10px;" > 打印测试 </button> </div>
angular.module('yourAppModule') .controller('PrinterController', function($scope, UsbPrinterService) { $scope.isConnected = false; $scope.isConnecting = false; $scope.connectedDevice = null; // 页面初始化时检查是否有已连接的打印机 $scope.init = async function() { try { const devices = await UsbPrinterService.getConnectedDevices(); if (devices.length > 0) { $scope.connectedDevice = devices[0]; $scope.isConnected = true; $scope.$apply(); // 异步操作后手动触发AngularJS视图更新 } } catch (error) { console.error('初始化检查设备失败:', error); } }; // 连接打印机的核心方法 $scope.connectPrinter = async function() { $scope.isConnecting = true; $scope.$apply(); // 立即更新按钮状态 try { let targetDevice; // 先检查是否已有已连接的设备 const existingDevices = await UsbPrinterService.getConnectedDevices(); if (existingDevices.length > 0) { targetDevice = existingDevices[0]; } else { // 没有已连接设备,请求用户选择 targetDevice = await UsbPrinterService.requestDevice(); } // 打开并配置设备 await UsbPrinterService.openDevice(targetDevice); $scope.connectedDevice = targetDevice; $scope.isConnected = true; alert('打印机连接成功!'); } catch (error) { alert(`连接失败:${error.message}`); } finally { $scope.isConnecting = false; $scope.$apply(); // 恢复按钮状态 } }; // 打印测试内容(扩展功能) $scope.printTest = async function() { if (!$scope.isConnected) return; // 转成ESC/POS支持的字节数据,这里打印测试文本+换行 const testText = new TextEncoder().encode('测试打印内容\n'); await UsbPrinterService.sendPrintData($scope.connectedDevice, testText); }; // 页面加载时执行初始化 $scope.init(); });
关键注意事项
- 异步操作与
$apply():WebUSB API是异步的,AngularJS无法自动检测异步操作后的变量变化,所以需要手动调用$scope.$apply()触发视图更新。 - 环境要求:WebUSB API只能在HTTPS环境下使用(localhost除外),所以测试或部署时要确保站点是HTTPS协议。
- 设备参数适配:不同品牌的ESC/POS打印机的配置接口、端点可能不同,需要根据打印机的官方说明书调整
selectConfiguration、claimInterface和端点参数。 - 错误处理:一定要保留完整的错误捕获逻辑,覆盖用户拒绝设备访问、设备断开、通信失败等场景,给用户明确的提示。
内容的提问来源于stack exchange,提问作者Sudip dey
相关产品推荐
相关产品推荐

