Web3.js 4.x版本事件监听详解:从HTTP到WebSocket的迁移

项目场景

在一个使用以太坊区块链技术的项目中,需要监听智能合约的事件,以便在事件触发时能够及时响应。项目中使用了web3.js库的4.x版本,节点使用Geth启动,并通过HTTP与节点进行通信。
在这里插入图片描述


问题描述

合约DataStorage.sol文件已经定义好了如下如下两个事件

通过hardhat项目进行编译部署得到合约,在编译得到的ABI中同样存在事件,编译部署全都正常
在这里插入图片描述

此时启动一个nodejs后端服务去用web3调用监听事件,首先通过geth结点实例化一个web3对象
在这里插入图片描述
web3.eth.Contract(ABI, ADDRESS)实例化合约,以下为监听事件的代码:
在这里插入图片描述
但是当触发该事件后,并没有进行监听,控制台也没出现任何打印或是其它信息


原因分析

经过查阅资料🚪web3官方文档🚪后我发现原因为如下两个:

  1. 事件监听必须使用WebSocketHTTP协议单向无法监听到事件
    WebSocket vs HTTP:
    HTTP协议只能单向通信,客户端需要不断发送请求以轮询获取更新,这在实时性要求高的场景下效率较低。
    WebSocket协议支持双向通信,服务端可以主动推送消息到客户端,客户端也可以主动向服务器发送信息(注意 Express 服务在与节点程序通信时,节点是作为服务端角色)适合事件监听这种需要实时响应的场景。

  2. web3.js 4.x版本下监听事件已经不支持用回调函数,得通过返回的对象来.on监听对象'data'或者'error'
    web3.js 4.x版本变化:
    web3.js 4.x版本中,监听事件时不再支持通过回调函数的方式,而是需要使用返回的对象并通过on方法来监听dataerror事件。这种方式更符合现代JavaScript的事件处理模式,也更具可读性和维护性。


解决方案

1. 启动WebSocket服务

如果是使用 geth 节点需要使用选项 --ws 开启服务,开发使用的Ganache默认开启了WebSocket服务。

geth --datadir "." --dev --dev.period 2 --http --http.api eth,web3,net --http.corsdomain "http://remix.ethereum.org" --password password.txt --http.port 8888 --ws --ws.api eth,web3,net --ws.origins "*" --ws.addr "127.0.0.1" --ws.port 8546

2. 初始化Web3并使用WebSocketProvider

在初始化web3时,使用了 WebsocketProvider来初始化Web3实例,通过 WebSocket 通信协议与节点通信

const { Web3 } = require('web3');
const web3 = new Web3(new Web3.providers.WebsocketProvider('ws://127.0.0.1:8546'));

3. 定义和监听智能合约事件

每个事件监听器应该独立定义,监听事件时,不再使用回调函数,而是使用 on 方法来监听 dataerror 事件。

const contract = new web3.eth.Contract(contractABI, contractAddress);

// 监听合约事件并记录日志
const dataStoredSubscription = contract.events.DataStored({
  fromBlock: 'latest'
});

dataStoredSubscription.on('data', event => {
  console.log('DataStored event:', event.returnValues);
});
dataStoredSubscription.on('error', error => {
  console.error('Error on DataStored event:', error);
});

通过以上步骤,可以实现对智能合约事件的实时监听,并且能够处理可能发生的错误。这样既提高了代码的可读性和维护性,又确保了事件监听的实时性和可靠性。

  • 11
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值