ethers.js调用智能合约Promise未等待执行,UI回调提前触发排查
问题排查与修复方案
你的问题出在两个核心点上:
1. getAllowance函数存在返回值漏洞
当signedTokenContract为undefined时,signedTokenContract?.allowance(...)会直接返回undefined,而你的代码未处理这种情况,函数会默认返回undefined(async函数会自动把这个值包装成已resolve的Promise)。另外,catch块捕获错误后仅打印日志,没有重新抛出错误,导致错误被“吞掉”,Promise依然会resolve为undefined,这是你拿到undefined的核心原因。
2. useLayoutEffect中混用await和then
你同时使用await和.then(),不仅逻辑冗余,还会造成混淆。这里await的是.then()的返回值(.then()的回调没有返回值,所以默认返回undefined),进一步加剧了问题。
修正后的getAllowance函数
async function getAllowance(address: string) { try { if (!contrastState) { throw new Error('Contract or signer is null or undefined, check connect method results'); } // 明确检查合约实例是否存在,避免可选链的静默失败 if (!signedTokenContract) { throw new Error('signedTokenContract is undefined'); } // allowance本身返回Promise,async函数会自动包装,无需额外await return signedTokenContract.allowance(address, contrastState.address); } catch (e) { console.log('connect error', e); // 重新抛出错误,让调用方可以捕获并处理 throw e; } }
修正后的useLayoutEffect代码
useLayoutEffect(() => { async function initialize() { setLoading(true); try { const allowance = await getAllowance(address); setAllowedNumber(allowance); console.log('Then allowance ' + allowance); } catch (e) { // 这里可以添加用户友好的错误提示 console.error('Failed to fetch allowance:', e); } finally { // 无论成功失败,都重置loading状态 setLoading(false); } } initialize(); }, [address]); // 把address加入依赖数组,避免闭包过期问题
内容的提问来源于stack exchange,提问作者xcsob
相关产品推荐
相关产品推荐

