Electron使用@nut-tree/nut-js自动输入时切换至浏览器打字速度变慢如何解决
问题解决方法
问题根源
@nut-tree/nut-js在向外部应用发送系统级输入事件时,默认开启了输入事件可靠性校验,会等待上一个按键事件被系统确认消费后才发送下一个,你设置的autoDelayMs仅控制按键间隔,没有修改这个校验等待的默认值,同时你将nut-js逻辑放在Electron渲染进程中调用,渲染进程较低的调度优先级也会拖慢跨进程输入事件的发送速度。而在Electron内部输入时属于同进程内交互,不需要跨进程校验,所以速度符合预期。
修复步骤
- 调整nut-js全局配置,关闭不必要的校验等待,开启事件批量提交:
在nut-js初始化配置处新增以下参数:
keyboard.config.autoDelayMs = 15; keyboard.config.keyPressDelayMs = 5; // 单个按键按下抬起的间隔,默认值远高于5ms keyboard.config.hidEventSharing = true; // 开启输入事件批量提交,减少系统调用开销
- 将nut-js调用逻辑从渲染进程迁移到Electron主进程,通过IPC触发输入操作,主进程更高的调度优先级可以降低跨进程系统调用的开销:
- 修改主进程index.js代码:
const { app, BrowserWindow, ipcMain } = require('electron'); const path = require('path'); const { keyboard } = require('@nut-tree/nut-js'); // 主进程提前初始化nut-js配置 keyboard.config.autoDelayMs = 15; keyboard.config.keyPressDelayMs = 5; keyboard.config.hidEventSharing = true; const delay = ms => new Promise(resolve => setTimeout(resolve, ms)) // Handle creating/removing shortcuts on Windows when installing/uninstalling. if (require('electron-squirrel-startup')) { // eslint-disable-line global-require app.quit(); } const createWindow = () => { // Create the browser window. const mainWindow = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true, contextIsolation: false, } }); // and load the index.html of the app. mainWindow.loadFile(path.join(__dirname, 'index.html')); // Open the DevTools. mainWindow.webContents.openDevTools(); }; // 新增IPC监听,处理输入请求 ipcMain.handle('trigger-type', async (_, inputText) => { await delay(3000); await keyboard.type(inputText); return true; }) // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. app.on('ready', createWindow); // Quit when all windows are closed. app.on('window-all-closed', () => { // On OS X it is common for applications and their menu bar // to stay active until the user quits explicitly with Cmd + Q if (process.platform !== 'darwin') { app.quit(); } }); app.on('activate', () => { // On OS X it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. if (BrowserWindow.getAllWindows().length === 0) { createWindow(); } });
- 修改渲染进程typer.js代码:
const { ipcRenderer } = require('electron'); const lol = document.getElementById('lol'); const input = `how to solve this problem`; lol.onclick = async() => { await ipcRenderer.invoke('trigger-type', input); }
- Windows系统下额外配置:
系统级输入操作会受UAC权限限制,开发时请用管理员权限启动运行项目的终端/编辑器,打包时在package.json的Windows打包配置中添加"requestedExecutionLevel": "requireAdministrator",获取足够的输入事件发送权限。
内容的提问来源于stack exchange,提问作者Tyrcnex
相关产品推荐
相关产品推荐

