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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 23:41:10