本文首发于深刻浅出区块链社区
原文连接:搞懂 Solidity 事件 Event - 如何在 DApp 中使用原文已更新,请读者前往原文阅读html
不少同窗对Solidity 中的Event有疑问,这篇文章就来详细的看看Solidity 中Event到底有什么用?git
Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊、智能合约有所了解,若是你还不了解,建议你先看以太坊是什么,另外
本文在监听合约事件是对上一篇Web3与智能合约交互实战进行补充,若是阅读了上一篇能够更好的理解本文。github
事件是以太坊虚拟机(EVM)日志基础设施提供的一个便利接口。当被发送事件(调用)时,会触发参数存储到交易的日志中(一种区块链上的特殊数据结构)。这些日志与合约的地址关联,并记录到区块链中.
来捋这个关系:区块链是打包一系列交易的区块组成的链条,每个交易“收据”会包含0到多个日志记录,日志表明着智能合约所触发的事件。web
在DAPP的应用中,若是监听了某事件,当事件发生时,会进行回调。
不过要注意:日志和事件在合约内是没法被访问的,即便是建立日志的合约。编程
在Solidity 代码中,使用event 关键字来定义一个事件,如:浏览器
event EventName(address bidder, uint amount);
这个用法和定义函数式同样的,而且事件在合约中一样能够被继承。触发一个事件使用emit(说明,以前的版本里并不须要使用emit),如:数据结构
emit EventName(msg.sender, msg.value);
触发事件能够在任何函数中调用,如:编程语言
function testEvent() public { // 触发一个事件 emit EventName(msg.sender, msg.value); }
经过上面的介绍,可能你们仍是不清楚事件有什么做用,若是你跟过Web3与智能合约交互实战这篇文章,你会发现点击"Updata Info"按钮以后,虽然调用智能合约成功,可是当前的界面并无获得更新。
使用事件监听,就能够很好的解决这个问题,让看看如何实现。ide
先回顾一下合约代码:函数
pragma solidity ^0.4.21; contract InfoContract { string fName; uint age; function setInfo(string _fName, uint _age) public { fName = _fName; age = _age; } function getInfo() public constant returns (string, uint) { return (fName, age); } }
首先,须要定义一个事件:
event Instructor( string name, uint age );
这个事件中,会接受两个参数:name 和 age , 也就是须要跟踪的两个信息。
而后,须要在setInfo函数中,触发Instructor事件,如:
function setInfo(string _fName, uint _age) public { fName = _fName; age = _age; emit Instructor(_fName, _age); }
在Web3与智能合约交互实战, 点击"Updata Info"按钮以后,会调用setInfo函数,函数时触发Instructor事件。
如今须要使用Web3监听事件,刷新UI。
先回顾下以前的使用Web3和智能合约交互的代码:
<script> if (typeof web3 !== 'undefined') { web3 = new Web3(web3.currentProvider); } else { // set the provider you want from Web3.providers web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:7545")); } web3.eth.defaultAccount = web3.eth.accounts[0]; var infoContract = web3.eth.contract(ABI INFO); var info = infoContract.at('CONTRACT ADDRESS'); info.getInfo(function(error, result){ if(!error) { $("#info").html(result[0]+' ('+result[1]+' years old)'); console.log(result); } else console.error(error); }); $("#button").click(function() { info.setInfo($("#name").val(), $("#age").val()); }); </script>
如今能够不须要 info.getInfo()来获取信息,而改用监听事件获取信息,先定义一个变量引用事件:
var instructorEvent = info.Instructor();
而后使用.watch()方法来添加一个回调函数:
instructorEvent.watch(function(error, result) { if (!error) { $("#info").html(result.args.name + ' (' + result.args.age + ' years old)'); } else { console.log(error); } });
代码更新以后,能够在浏览器查看效果,这是点击"Updata Info"按钮以后,会及时更新界面,如图:
完整的代码请订阅小专栏区块链技术查看。
有时咱们会有这样的需求:获取当前全部姓名及年龄记录,或者是,要过滤出年龄28岁的记录,应该如何作呢?
以及另一个常见的场景:想要获取到代币合约中全部的转帐记录,也一样须要使用事件过滤器功能,这部份内容请你们订阅小专栏区块链技术阅读。
<!--
有时咱们会有这样的需求:获取当前全部姓名及年龄记录,应该如何作呢?
实际上事件支持过滤器,能够从全部的区块中过滤出符合要求的事件,如:
var instructorEvent = info.Instructor({}, {fromBlock: 0, toBlock: 'latest'});
或者是,要过滤出年龄28岁的记录,能够这样:
var instructorEvent = info.Instructor({ 'age': 28});
好比,咱们要获取到代币合约中,全部的转帐记录, 就能够使用:
var transferEvent = token.Transfer({}, {fromBlock: 0, toBlock: 'latest'}) var transferEvent.watch(function(error, result){ // handle result.args.from result.args.to });
-->
https://coursetro.com/posts/c...
https://github.com/ethereum/w...
☛ 深刻浅出区块链 - 系统学习区块链,打造最好的区块链技术博客。
☛ 个人知识星球为各位解答区块链技术问题,欢迎加入讨论。
☛ 关注公众号“深刻浅出区块链技术”第一时间获取区块链技术信息。