ClojureScript中Web3 1.5.2部署合约Promise无法resolve问题如何修复
修复方案
核心原因
web3.js 1.5.2版本的contract.deploy().send()方法存在已知行为异常:如果调用send时同时传入回调函数、绑定事件监听并等待Promise返回,会导致Promise无法正常resolve,即使交易已经完成链上确认,这是导致你问题的核心诱因。
修复步骤
- 移除
send方法的回调参数
你当前代码中给send传入了打印错误和交易哈希的回调,回调和Promise模式混用会触发web3.js的bug,把这部分逻辑迁移到error事件和sending事件中处理即可。 - 调整确认数配置(可选)
你配置的transactionConfirmationBlocks: 3需要和部署链的出块规则匹配,测试时可以临时改为1,确认逻辑跑通后再调整为合适的数值。 - 兜底方案:直接在
receipt事件中完成后续逻辑
如果修改后Promise仍然无法正常resolve,直接在receipt事件回调中通过返回的合约地址手动初始化合约实例,执行后续的dispatch逻辑,不需要等待Promise resolve。
修改后的代码示例
(go (let [web3 (Web3. (.-givenProvider Web3)) ego (-> (<p! (.. web3 -eth (getAccounts))) (nth 0)) contract (new (.. web3 -eth -Contract) (.-abi (js/JSON.parse contract-json)) nil (clj->js {:transactionConfirmationBlocks 3})) contract-deploy (.. contract (deploy (clj->js {:arguments [ipfs] :data (.-bytecode (js/JSON.parse contract-json))})))] ;;(prn "ego is " ego) (let [contract-send (.. contract-deploy ;; 移除send的回调参数,避免混用回调和Promise模式 (send (clj->js {:from ego}))) contract-instance (try (<p! (.. contract-send (on "error" (fn [obj] (prn "err is " obj) (js/console.log "error " obj))) (on "sending" (fn [obj] (prn "sending " obj) ;; sending事件的payload中可直接获取tx hash (prn "tx hash is " (.-hash obj)))) (on "receipt" (fn [receipt] (prn "contract address is" (.-contractAddress receipt)))) (on "confirmation" (fn [confirmation-number receipt] (dispatch [:stop-loading]) (prn "confirmation number" confirmation-number) (prn "receipt" receipt))))) (catch js/Object e (.log js/console "contract error " e)))] (when contract-instance (dispatch [:issue-nfts contract-instance contract-json ego]))))
兜底方案代码
如果调整后Promise仍然无法resolve,直接在receipt事件中触发后续逻辑即可,完全不需要等待Promise返回:
(on "receipt" (fn [receipt] (prn "contract address is" (.-contractAddress receipt)) ;; 手动初始化合约实例 (let [contract-instance (new (.. web3 -eth -Contract) (.-abi (js/JSON.parse contract-json)) (.-contractAddress receipt))] (dispatch [:issue-nfts contract-instance contract-json ego]))))
内容的提问来源于stack exchange,提问作者zendevil.eth
相关产品推荐
相关产品推荐

