React中使用WebWorker处理RSA密钥生成等耗时任务避免页面假死
React生成RSA密钥避免页面假死解决方案
核心思路是将CPU密集型的密钥生成任务完全放到Web Worker线程执行,不占用主线程的渲染、交互资源,你现有方案的方向正确,只需要修正以下问题即可:
1. 修正Web Worker代码
首先单独创建Worker文件 src/workers/rsaGenerator.worker.js,代码如下:
// 不需要export default,直接绑定Worker全局的onmessage事件 import NodeRSA from 'node-rsa'; self.onmessage = function() { // 需生成2048位则修改参数b为2048,原有代码写的是4096位 const keysPair = new NodeRSA({ b: 2048 }); const pubKey = keysPair.exportKey('public').replace(/(\r\n|\n|\r)/gm,""); const privKey = keysPair.exportKey('private'); self.postMessage({ pubKey, privKey }); // 任务完成后关闭Worker释放资源 self.close(); }
2. 修正React组件内的Worker调用逻辑
先根据你的构建工具导入Worker:
- Vite项目导入方式:
// 组件顶部导入,注意后缀加?worker import RsaKeyWorker from './workers/rsaGenerator.worker.js?worker';
- CRA(create-react-app)项目导入方式:
// 组件顶部导入 const RsaKeyWorker = require('./workers/rsaGenerator.worker.js');
修正useEffect逻辑,增加异常处理、资源销毁、就绪通知:
// 提前申请系统通知权限,用于生成完成后通知用户 useEffect(() => { if (Notification.permission === 'default') { Notification.requestPermission(); } }, []); useEffect(() => { const keysWorker = new RsaKeyWorker(); keysWorker.postMessage("start"); keysWorker.onmessage = (e) => { setPrivKey(e.data.privKey); setPubKey(e.data.pubKey); setKeyStatus('密钥生成完成,可下载!'); setGenState(1); // 触发桌面就绪通知 if (Notification.permission === 'granted') { new Notification('密钥生成完成', { body: '您的RSA密钥对已生成,可以下载私钥后进入平台' }); } }; // 监听Worker报错 keysWorker.onerror = (error) => { console.error('密钥生成失败', error); setKeyStatus('密钥生成失败,请刷新页面重试'); }; // 组件卸载时销毁Worker,避免内存泄漏 return () => { keysWorker.terminate(); }; }, []);
3. 可选优化:用浏览器原生Web Crypto API提升性能
如果觉得NodeRSA依赖较重,可以替换为浏览器原生加密API生成密钥,性能提升30%以上,不需要额外引入第三方依赖,Worker代码修改为:
self.onmessage = async function() { // 生成2048位RSA密钥对 const keyPair = await crypto.subtle.generateKey( { name: "RSA-OAEP", modulusLength: 2048, publicExponent: new Uint8Array([0x01, 0x00, 0x01]), hash: "SHA-256" }, true, ["encrypt", "decrypt"] ); // 导出公钥并格式化 const pubKeyBuffer = await crypto.subtle.exportKey("spki", keyPair.publicKey); const pubKey = btoa(String.fromCharCode(...new Uint8Array(pubKeyBuffer))); // 导出私钥并格式化 const privKeyBuffer = await crypto.subtle.exportKey("pkcs8", keyPair.privateKey); const privKey = `-----BEGIN PRIVATE KEY-----\n${btoa(String.fromCharCode(...new Uint8Array(privKeyBuffer))).match(/.{1,64}/g).join('\n')}\n-----END PRIVATE KEY-----`; self.postMessage({ pubKey, privKey }); self.close(); }
内容的提问来源于stack exchange,提问作者tomas
相关产品推荐
相关产品推荐

