如何降低ethers.js事件监听器引发的RPC方法调用频率?
如何降低ethers.js事件监听器的RPC调用频率?
当使用ethers.js的contract.on()监听合约事件时,默认采用HTTP轮询模式,会以较短间隔重复调用eth_blockNumber、eth_getLogs等RPC方法,导致Hardhat节点频繁打印相关日志。你可以通过以下几种方式优化:
1. 自定义轮询间隔
在初始化HTTP Provider时,通过pollingInterval参数设置轮询间隔(单位:毫秒),延长查询周期:
// 初始化Provider时指定10秒轮询间隔 const provider = new ethers.providers.JsonRpcProvider("http://localhost:8545", { pollingInterval: 10000 }); const contract = new ethers.Contract(contractAddress, abi, provider); contract.on("Transfer", (to, amount, from) => { // 事件处理逻辑 });
注意:间隔越长,事件触发的实时性越低,需根据业务需求平衡选择。
2. 切换为WebSocket Provider
如果节点支持WebSocket(Hardhat节点默认开启ws://localhost:8545),使用WebSocket连接替代HTTP轮询。WebSocket采用推送模式,仅当链上有新块或事件时才会触发数据传输,大幅减少RPC调用:
// 初始化WebSocket Provider const provider = new ethers.providers.WebSocketProvider("ws://localhost:8545"); const contract = new ethers.Contract(contractAddress, abi, provider); contract.on("Transfer", (to, amount, from) => { // 事件处理逻辑 }); // 程序退出时关闭连接,避免内存泄漏 process.on("SIGINT", () => { provider.destroy(); process.exit(); });
3. 手动控制日志查询(进阶)
完全自定义事件查询逻辑,通过定时器定期查询指定块范围的日志,精准控制查询频率:
const provider = new ethers.providers.JsonRpcProvider("http://localhost:8545"); const contract = new ethers.Contract(contractAddress, abi, provider); // 记录上次查询的块号 let lastProcessedBlock = await provider.getBlockNumber(); // 每30秒查询一次新块中的事件 setInterval(async () => { const currentBlock = await provider.getBlockNumber(); if (currentBlock > lastProcessedBlock) { // 查询从上次块之后到当前块的Transfer事件 const logs = await contract.queryFilter( "Transfer", lastProcessedBlock + 1, currentBlock ); logs.forEach(log => { const { to, amount, from } = log.args; // 处理单条事件逻辑 }); lastProcessedBlock = currentBlock; } }, 30000);
内容的提问来源于stack exchange,提问作者goodUser
相关产品推荐
相关产品推荐

