最新內容會更新在主站深入淺出區塊鏈社區
原文鏈接:搞懂 Solidity 事件 Event - 如何在 DApp 中使用
很多同學對Solidity 中的Event有疑問,這篇文章就來詳細的看看Solidity 中Event到底有什么用?
寫在前面
Solidity 是以太坊智能合約編程語言,閱讀本文前,你應該對以太坊、智能合約有所了解,如果你還不了解,建議你先看以太坊是什么,另外
本文在監聽合約事件是對上一篇Web3與智能合約交互實戰進行補充,如果閱讀了上一篇可以更好的理解本文。
什么是事件Evnet
事件是以太坊虛擬機(EVM)日志基礎設施提供的一個便利接口。當被發送事件(調用)時,會觸發參數存儲到交易的日志中(一種區塊鏈上的特殊數據結構)。這些日志與合約的地址關聯,並記錄到區塊鏈中.
來捋這個關系:區塊鏈是打包一系列交易的區塊組成的鏈條,每一個交易“收據”會包含0到多個日志記錄,日志代表着智能合約所觸發的事件。
在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"按鈕之后,雖然調用智能合約成功,但是當前的界面並沒有得到更新。
使用事件監聽,就可以很好的解決這個問題,讓看看如何實現。
修改合約,定義事件及觸發事件
先回顧一下合約代碼:
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監聽事件,刷新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歲的記錄,應該如何做呢?
以及另外一個常見的場景:想要獲取到代幣合約中所有的轉賬記錄,也同樣需要使用事件過濾器功能,這部分內容請大家訂閱小專欄區塊鏈技術閱讀。
參考視頻
我們也推出了目前市面上最全的視頻教程:深入詳解以太坊智能合約語言Solidity
目前我們也在招募體驗師,可以點擊鏈接了解。
參考文章
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
☛ 深入淺出區塊鏈 - 系統學習區塊鏈,打造最好的區塊鏈技術博客。
☛ 我的知識星球為各位解答區塊鏈技術問題,歡迎加入討論。
☛ 關注公眾號“深入淺出區塊鏈技術”第一時間獲取區塊鏈技術信息。