上一篇成功透過 web3.js 來呼叫合約中的函式。我們之前設計的函式只要會變更狀態變數的操作都會記錄 log ,也就是觸發 event ,那要怎麼去監聽 event 就是我們今天的重點~!
我們回憶一下,當交易在 pending 的時候還沒有正式的寫入區塊鏈中,而當交易完成後我們要如何優雅的得知交易已經完成呢?前面有提到 log 是存在收據中,而收據是在交易完成後所產生,所以我們只要監聽 log 是否寫入就可以得知交易是否完成,並在前端處理後續動作。另一個用途就是寫 log 的成本相對低很多,但智能合約無法去存取 log 裡的資料,所以透過前端監聽來取得 log 資訊,再做其他的處理。
監聽 Event 有很多種函式可以使用,還可以設置 options
來針對訂閱的內容做過濾等動作,提供的參數有:
{ myIndexedParam: [20,23] }
,是指 myIndexedParam
為20或23的事件,型別為 Object
number
number
topics
,型別為 Array
topics 在後方會有較詳細的說明!
為了方便管理,我們新增一個 type 在 contract.ts
中,用來定義 options
的參數格式:
export interface EventLogOptions {
filter?: Object;
fromBlock?: number;
toBlock?: number;
topics?: Array<any>;
}
訂閱事件,取得一項資料後取消訂閱,與 rxjs
的 take(1)
意思相同。我們在 app.component.ts
中使用,要訂閱 Event 就要取得合約實例後透過實例來訂閱。我們的合約僅有一個 done
事件,所以就將該事件名稱作為第一個參數,若要設置 options
則放在第二個參數,最後一個為 callback
,用來執行收到監聽結果後的操作。
constructor(private provider: ProviderService) {
const resume = this.provider.getResume('0x1Ff192E4bA1b23bdb586A290C525b6037f8859a8');
resume.once('done', (err, event) => {
console.log(event);
});
}
然後透過 Truffle 來呼叫合約,再打開開發人員工具來看(我把主題換深色系了):
可以看到 returnValues
裡面就是 log 的資料。
從實例的 events
中取出要監聽的事件並訂閱,與 once
不同的就是會不斷監聽直到關閉:
constructor(private provider: ProviderService) {
const resume = this.provider.getResume('0x1Ff192E4bA1b23bdb586A290C525b6037f8859a8');
resume.events.done()
.on('data', event => {
console.log(event);
});
}
可以取得過去已經發生的事件,我們設置 options
來取得區塊0到最新區塊的所有事件,回傳的會是陣列:
constructor(private provider: ProviderService) {
const resume = this.provider.getResume('0x1Ff192E4bA1b23bdb586A290C525b6037f8859a8');
const eventOption = {
fromBlock: 0
} as EventLogOptions;
resume.getPastEvents('done', eventOption, (err, events) => {
console.log(events);
});
}
執行結果:
能夠監聽事件來判斷是否交易完成,並取用 log 中的資訊。其實 Event 對於 DApp 來說就像是一種溝通的橋樑,能夠讓區塊鏈與應用程式用較低的成本做到互動的效果,也算是很重要的功能之一!