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)) ])
- 确认Solidity合约中
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中必须正确定义该结构体,否则解析会失败。
- 在全局添加未处理Promise拒绝监听,查看真实错误:
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
相关产品推荐
相关产品推荐

