You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

getAllShipment函数无法从智能合约正常获取数据求助

问题排查:getAllShipment函数无法执行到console.log(3)

核心原因分析

你的代码在执行await contract.getAllTransactions()时出现了静默卡住或未被捕获的异步错误,导致后续代码无法执行,且catch块未捕获到异常。常见场景包括合约调用无限等待、控制台打印循环引用对象卡死、ABI不匹配导致解析失败。

分步排查与解决办法

1. 检查合约调用是否无限等待

  • 可能原因:
    • getAllTransactions不是view/pure函数,调用时需要用户签名,但钱包未弹出授权窗口或用户未确认交易,导致代码一直等待Promise完成。
    • 节点连接不稳定,请求超时但未触发错误。
  • 解决步骤:
    • 确认Solidity合约中getAllTransactions的修饰符:必须添加view或pure(如果不修改链上状态),示例:
      function getAllTransactions() public view returns (Shipment[] memory) {
          // 函数逻辑
      }
      
    • 改用只读合约实例调用,避免签名等待:将signer替换为provider创建合约,视图函数不需要用户签名:
      const contract = new ethers.Contract(ContractAddress, ContractABI, provider)
      
    • 添加超时机制,避免无限等待:
      const shipments = await Promise.race([
          contract.getAllTransactions(),
          new Promise((_, reject) => setTimeout(() => reject(new Error('合约调用超时')), 10000))
      ])
      

2. 排查控制台打印导致的卡死

  • 可能原因:ethers返回的shipments包含循环引用对象(比如BigNumber实例、合约内部对象),直接console.log(shipments)会导致浏览器控制台卡死,看起来像是未执行到console.log(3)。
  • 解决步骤:
    • 替换打印方式为JSON.stringify,避免循环引用:
      console.log(JSON.stringify(shipments))
      

3. 捕获未被try/catch拦截的错误

  • 可能原因:某些异步错误(比如节点连接中断、ABI不匹配)未被try/catch捕获,属于未处理的Promise拒绝。
  • 解决步骤:
    • 在全局添加未处理Promise拒绝监听,查看真实错误:
      window.addEventListener('unhandledrejection', (event) => {
          console.error('未处理的Promise错误:', event.reason);
      });
      
    • 检查ABI中getAllTransactions的返回类型是否与合约完全匹配:如果合约返回的是自定义结构体数组,ABI中必须正确定义该结构体,否则解析会失败。

4. 提前防范数据解析错误(预排查)

虽然代码还没执行到map步骤,但提前确认合约返回数据的结构:

  • 确认每个字段(sender/receiver/pickupTime等)都存在且类型正确(比如pickupTime是uint256,对应ethers的BigNumber)。
  • 在map中添加可选链操作,避免undefined导致的后续错误:
    pickupTime: shipment.pickupTime?.toNumber() || 0
    

修改后的完整示例代码

const getAllShipment = async () => {
    try {
        console.log("1")
        const provider = new ethers.providers.Web3Provider(window.ethereum)
        // 视图函数使用provider创建只读合约实例
        const contract = new ethers.Contract(ContractAddress, ContractABI, provider)
        
        console.log("2")
        // 添加超时处理,防止无限等待
        const shipments = await Promise.race([
            contract.getAllTransactions(),
            new Promise((_, reject) => setTimeout(() => reject(new Error('合约调用超时')), 10000))
        ])
        // 安全打印返回数据
        console.log(JSON.stringify(shipments))
        console.log("3")
        const allShipments = shipments.map((shipment) => ({
            sender: shipment.sender,
            receiver: shipment.receiver,
            price: ethers.utils.formatEther(shipment.price.toString()),
            pickupTime: shipment.pickupTime?.toNumber() || 0,
            deliveryTime: shipment.deliveryTime?.toNumber() || 0,
            distance: shipment.distance?.toNumber() || 0,
            isPaid: shipment.isPaid,
            status: shipment.status,
        }));

        return allShipments;
    } catch (error) {
        console.error("Something went wrong", error);
        throw error; // 抛出错误让调用者可以处理
    }
}

// 全局监听未处理的Promise拒绝
window.addEventListener('unhandledrejection', (event) => {
    console.error('未处理的Promise错误:', event.reason);
});

内容的提问来源于stack exchange,提问作者ALISHA REDDY

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 10:15:58