Solidity

在實際設置數據之前觸發事件

  • May 29, 2018

假設這是我的智能合約:

 event NewUser(
   address userAddress,
   uint amount
 );
 function addUser() public payable{
   require(msg.value <= maxValue && msg.value > 0);
   require(allowedValues[msg.value]);
   require(accountAmount() < 5);

   if (users[msg.sender] > 0) {
       userPullout(); //Remove senders data
   }

   userAddresses.push(msg.sender);
   partAmounts.push(msg.value);// This value doesn't get pushed before the event is finished
   users[msg.sender] = msg.value;

   emit NewUser(msg.sender, msg.value);//This is called to soon
}

這是我的 nodeJS 文件:

app.contract.events.NewUser({}, function(error, event){})
.on('data', function(event){
 io.emit('new user', event.returnValues);
}).on('change', function(event){
 io.emit('new user', event.returnValues);
})
.on('error', console.error);

如果我partAmount使用函式將數組記錄在 web3 中.call,則仍會返回事件之前的舊值。這告訴我事件觸發得太早了。

設置數據後是否有呼叫事件?

編輯:更多程式碼。

const socket = openSocket('http://localhost:3000'); // subscribed to the socket server firing the events from node back-end
socket.on('new user', (event) => {
 console.log(event) // returns for example 7 which is CORRECT
 this.props.contract.methods.getCertainArray().call(this.props.contractObject, (err, res) => {
   console.log(res); // old data from before the event so if the previous array was [0, 6 , 6], this would still be returned NOTICE: no 7 in the array yet.
 });
})

注意:如果我像這樣在呼叫函式周圍設置超時:

setTimeout(() => {
   this.props.contract.methods.getCertainArray().call(this.props.contractObject, (err, res) => {
     console.log(res); // old data from before the event so if the previous array was [0, 6 , 6], this would still be returned NOTICE: no 7 in the array yet.
   });
}, 5000);

它確實返回了正確的數組,但這不是我希望腳本執行的方式。

問題是您沒有等待交易被探勘,然後.call再檢查結果。

它去:

  1. 簽署並發送交易。獲取交易收據。
  2. 交易被探勘,合約按順序執行指令。
  3. 區塊與確認的交易一起到達。
  4. 現在你可以call一個函式來看看效果。

或者,注意一個事件,就像您的範例 JS 出現的那樣。直到交易被包含在一個塊中,事件才會到達。

希望能幫助到你。

正如 Rob 指出的那樣,您很可能不會在提取數據之前等待交易被完全探勘。我不確定 web3js,但 Golang 提供了在交易被探勘之前讀取待處理狀態數據的能力。我個人更喜歡用 golang 編寫與智能合約互動的後端程式碼,並且只在需要時使用 web3(即前端程式碼)

不過要小心,我建議不要讀取待處理的狀態數據,因為這可能會根據插入到記憶體池中的任何事務而改變。

強烈建議在處理任何數據之前等待交易被探勘,我個人建議使用 golang over web3 與智能合約進行互動,並且僅在需要編寫前端程式碼時才使用 web3。

我有一個函式,只要在區塊鏈上發送特定交易,就會呼叫它,並在收到事件後自動完成處理並退出。

https://github.com/RTradeLtd/Temporal/blob/2dd19bd950e2864e2cbad904c3b7c94958499048/server/payments.go#L55

引用自:https://ethereum.stackexchange.com/questions/49746