Web3js

無法讀取未定義問題的“已部署”屬性

  • March 21, 2022

我正在嘗試啟動 Election-Dapp。我安裝了這些依賴項:

  • Nodejs v9.11.1

  • npm v5.8.0

  • Truffle v4.1.3

  • web3js v0.2

  • ganache-cli

下面是我的solidity合約

pragma solidity ^0.4.18;
contract Election {
   //model a candidate
   struct Candidate {
       uint id;
       string name;
       uint voteCount;
   }
   //fetch candidate
   mapping (uint => Candidate) public candidates;
   uint public candidatesCount;
   function Election() public {
       addCandidate("Blockchain");
       addCandidate("Groot");
   }
   function addCandidate(string _name) private {
       candidatesCount++;
       candidates[candidatesCount] = Candidate(candidatesCount, _name, 0);
   }
}

這是我的 Dapp 的 js 和 Web3:

   App = {
 web3Provider: null,
 contracts: {},
 account: "0x0",

 init: function() {
   return App.initWeb3();
 },

 initWeb3: function() {
   if(typeof web3 !== 'undefined'){
     App.web3Provider = web3.currentProvider;
     web3 = new Web3(web3.currentProvider);
   } else {
     App.web3Provider = new Web3.providers.HttpProvider('http://localhost:8545');
     web3 = new Web3(App.web3Provider);
   }
   return App.initContract();
 },

 initContract: function() {
   $.getJSON('Election.json', function(election) {
     //Instantiate a new truffle contract from the artifact
     App.contracts.Election = TruffleContract(election);
     //connect provider to interact with contract
     App.contracts.Election.setProvider(App.web3Provider);
   });
   return App.render();
 },

 render: function() {
   var electionInstance;
   var loader = $("#loader");
   var content = $("#content");

   loader.show();
   content.hide();

   //load account data
   web3.eth.getCoinbase(function(err, account) {
     if(err == null) {
       App.account = account;
       $("#accountAddress").html("Your account: " + account);
     }
   });

   //load contract data
   App.contracts.Election.deployed().then(function(instance) {
     electionInstance = instance;
     return electionInstance.candidatesCount();
   }).then(function(candidatesCount){
     var candidatesResults = $("#candidatesResults");
     candidatesResults.empty();

     for(let i = 1; i <= candidatesCount; i++) {
       electionInstance.candidates(i).then(function(candidate) {
         var id = candidate[0];
         var name = candidate[1];
         var voteCount = candidate[2];

         //render candidate results
         var candidateTemplate = "<tr><th>" + id + "</th><td>" + name + "</td><td>" + voteCount + "</td></tr>";
         candidatesResults.append(candidateTemplate);
       });
     }

     loader.hide();
     content.show();
   }).catch(function(error) {
       console.warn(error);
   });
 }
};

$(function() {
 $(window).load(function() {
   App.init();
 });
});

這是問題的截圖: 我可以通過 chrome 控制台查看我的契約

我還可以使用 truffle 控制台和 JS 承諾與我的契約進行互動,如下所示:

在此處輸入圖像描述

問題:為什麼它是未定義的?

PS:如果有幫助,這裡是我 GitHub 上這個項目的連結:

LINK TO GITHUB

任何幫助表示讚賞,謝謝。

正如@Ismael 正確指出的那樣,getJSON() 是一個非同步操作,在確保它完成之前呼叫 App.render() 會導致未定義的錯誤。但是,按照@Vlad 的建議使 getJSON() 同步並不是最佳做法,而是使用 .then() 或**.done()**來確保 getJSON() 在呼叫 render() 函式之前完成其操作。


initContract: function() { $.getJSON('Election.json', function(election) { //Instantiate a new truffle contract from the artifact App.contracts.Election = TruffleContract(election); //connect provider to interact with contract App.contracts.Election.setProvider(App.web3Provider); }).done(function() { return App.render(); }); }

問題是 $.getJSON 是非同步的。

將其設置為同步解決了這個問題。

$.ajaxSetup({async: false});  

感謝@Ismael 的幫助。

UPD:

由於不推薦使用同步 ajax,因此最好確保在實際獲得響應之前不呼叫 ajax 響應。

所以在我的情況下是這樣的:

 initContract: function() {
$.getJSON('Election.json', function(election) {
 //Instantiate a new truffle contract from the artifact
 App.contracts.Election = TruffleContract(election);
 //connect provider to interact with contract
 App.contracts.Election.setProvider(App.web3Provider);
 return App.render();
});
//return App.render();},  

我所做的只是App.render()從註釋掉到$.getJSON(){...}函式結束的地方替換。

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