無法讀取未定義問題的“已部署”屬性
我正在嘗試啟動 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(); }); });
我還可以使用 truffle 控制台和 JS 承諾與我的契約進行互動,如下所示:
問題:為什麼它是未定義的?
PS:如果有幫助,這裡是我 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(){...}
函式結束的地方替換。