本文首發於深刻淺出區塊鏈社區 原文連接:搞懂 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歲的記錄,應該如何作呢? 以及另一個常見的場景:想要獲取到代幣合約中全部的轉帳記錄,也一樣須要使用事件過濾器功能,這部份內容請你們訂閱小專欄區塊鏈技術閱讀。
<!-- 有時咱們會有這樣的需求:獲取當前全部姓名及年齡記錄,應該如何作呢? 實際上事件支持過濾器,能夠從全部的區塊中過濾出符合要求的事件,如: ```js var instructorEvent = info.Instructor({}, {fromBlock: 0, toBlock: 'latest'}); ``` 或者是,要過濾出年齡28歲的記錄,能夠這樣: ```js var instructorEvent = info.Instructor({ 'age': 28}); ``` 好比,咱們要獲取到代幣合約中,全部的轉帳記錄, 就可使用: ```js 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/code/100/Solidity-Events-Tutorial---Using-Web3.js-to-Listen-for-Smart-Contract-Events https://github.com/ethereum/wiki/wiki/JavaScript-API#contract-events
☛ 深刻淺出區塊鏈 - 系統學習區塊鏈,打造最好的區塊鏈技術博客。
☛ 個人知識星球爲各位解答區塊鏈技術問題,歡迎加入討論。
☛ 關注公衆號「深刻淺出區塊鏈技術」第一時間獲取區塊鏈技術信息。