Web3.js 中多個依賴請求的最佳實踐
希望獲得一些關於使用 Web3.js 的非常常見場景的建議
假設您要計算乙太坊地址中存在的特定 ERC20 代幣合約的代幣數量。
為了準確地做到這一點,您需要通過 Web3.js 獲取
balanceOf()
和decimals()
值,然後調整餘額以給出最終值。但是,這些 Web3 請求的最佳實踐是確保它們是非同步的,因此我們可能會在取回小數的不同時間取回餘額。
在返回這兩個值後顯示調整值的最佳方式是什麼?
根據我的簡短研究,您可以:
- 使用 JavaScript 承諾
- 使用 Web3.js 批處理
- 嵌套非同步呼叫
還有其他選擇嗎?從上述選項中是否有最佳選擇?還是場景驅動?
謝謝卡洛姆的幫助。經過一番研究,感覺promise在這裡是正確的做法,也是未來web3.js預設採用的方法。為了解決我今天的問題,這就是我最終要做的事情:
我發現這條評論建議了一個簡單的包裝器,我可以將它添加到我的項目中並用以下方式包裝我的 Web3.js 函式:
const promisify = (inner) => new Promise((resolve, reject) => inner((err, res) => { if (err) { reject(err) } else { resolve(res); } }) );
評論的作者然後提到用於
await
分配變數,但這對我不起作用。相反,我使用包裝器創建了一組Promise
函式,並讓它們都觸發一個Promise.all
.因此,對於我文章中的具體範例,這就是我所做的:
tokenContract = web3.eth.contract(contractABI).at(contractAddress) var dec = promisify(cb => tokenContract.decimals(cb)) var bal = promisify(cb => tokenContract.balanceOf(address, cb)) var tokName = promisify(cb => tokenContract.name(cb)) var tokSym = promisify(cb => tokenContract.symbol(cb)) Promise.all([dec, bal, tokName, tokSym]).then(function ([decimal, balance, tokenName, tokenSymbol]) { var adjustedBalance = balance / Math.pow(10, decimal) var output = adjustedBalance + " " + tokenSymbol + " (" + tokenName + ")"; console.log(output) })
輸出看起來像:
64.09856462716048 OMG (OMGToken)
我希望這對其他人也有幫助!
編輯:使外部函式非同步後,我能夠使這些
await
東西工作:async function getERC20Balance() { var address, contractABI, contractAddress, tokenContract, balance, decimals, tokenName, tokenSymbol, adjustedBalance address = document.getElementById("address").value contractAddress = document.getElementById("contractAddress").value contractABI = human_standard_token_abi tokenContract = web3.eth.contract(contractABI).at(contractAddress) decimals = promisify(cb => tokenContract.decimals(cb)) balance = promisify(cb => tokenContract.balanceOf(address, cb)) tokenName = promisify(cb => tokenContract.name(cb)) tokenSymbol = promisify(cb => tokenContract.symbol(cb)) adjustedBalance = await balance / Math.pow(10, await decimals) document.getElementById("tokenBalance").innerHTML = adjustedBalance; document.getElementById("tokenInfo").innerHTML = " " + await tokenSymbol + " (" + await tokenName + ")"; }
正如你所提到的,我認為選擇是基於場景的。具體來說,您的請求有多複雜以及需要進行多少次非同步呼叫。
其他要考慮的事情是(1)您對替代方案的熟悉程度,(2)您在程式碼庫的其餘部分中用於非同步呼叫的內容 - 最好保持一致性,以及(3)您的團隊對該方法的熟悉程度。
我將在其中添加另一個您未包含在列表中的內容:
- ES8 async/await(雖然我會保持這種風格:更簡單、更簡潔的 promises/chains 編碼方式)
在您的範例中,您只檢索了兩個變數,這非常簡單,因此您可能可以很好地使用回調/嵌套非同步呼叫。但是,您擁有的變數或非同步請求越多,這將很快開始變得混亂(“回調地獄”),更不用說解決整個鏈可能需要更長的時間,因為每個順序呼叫都會等到前一個呼叫解決直到啟動。
因此,一旦您有更多的非同步呼叫,您就可以從 Promise 中受益,因為 (1) 更簡潔的語法,以及 (2) 通過使用
Promise.all
.