使用 web3 的智能合约中的持久事件状态

Persistent event state in smart contract with web3

当合同中触发事件(某事)时,页面控制台按预期记录输出(通过 somethingEvent.watch()),但是当我重新加载页面时,它控制台记录相同的输出。最近的事件是要持续存在还是我没有正确使用它?谢谢

// Solidity
event Something(string message);

function doSomething(string newMessage) payable {
    Something(newMessage);
}

// Web3
var somethingEvent = contractInstance.Something();

somethingEvent.watch(function(error, result) {
  console.log(result.args.message);
});

只要你调用watch()并且最新的块号与上一次执行相同,就会发生这种情况。当事件为 "fired" 时,EVM 所做的只是在交易成功挖掘后将事件信息写入日志。

当你向合约添加手表时,你可以指定你想要开始监听的区块。如果你没有传递任何东西(正如你的代码所做的那样),它默认为最新的块(参见 filter API docs)。因此,当您重新加载页面并且尚未将新块添加到链中时,您将获得相同的事件。

如果您想避免重复事件,请使用result.blockNumber记住最后读取的块并在每次建立新手表时将其递增1。

let blockNumber = 'latest'; // should come from some state initially set to 'latest'

...

var somethingEvent = contractInstance.Something({}, {fromBlock: blockNumber);

somethingEvent.watch(function(error, result) {
  blockNumber = result.blockNumber + 1;
  console.log(result.args.message);
});

请注意,在这种情况下,watch 可能不是最好的选择。这取决于您的客户的状态。每当你完成对事件的监听时,你应该总是调用 stopWatching。如果您不想设置手表,您也可以使用 get 这将发送回所有符合您过滤条件的事件。