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

如何在JavaScript for循环中以异步返回的变量为上限进行迭代?

问题排查:NFT余额作为for循环上限时循环跳过的问题

我要给用户钱包地址关联的NFT做图片网格,已经实现了返回单张图片URL用于img标签的功能。现在需要返回多个URL展示钱包里所有NFT图片,得用for循环迭代到钱包的NFT余额。我能通过异步方法获取钱包NFT余额并转成数字,但把这个返回值当for循环上限时,循环直接跳过;用固定数字或普通变量做上限就正常运行。附上代码,请帮忙排查:

async getNFTMetadata() {
  let balance = Number(await contract.methods.balanceOf(this.currentUser.walletAddress).call());
  console.log(balance);
  console.log(typeof(balance));
  var num =3;
  console.log(typeof(num));
  for (let i = 1; i < Number(balance); i++) {
    const result = await contract.methods.tokenURI(i).call()
    const request = new Request(result);
    const response = await fetch(request);
    const metadata = await response.json();
    const image = metadata.image;
    console.log(metadata);
    console.log(result);
    console.log(image);
  }
  console.log(balance)
}

问题根源分析

  1. 循环条件不匹配:
    原代码循环条件是i < Number(balance),但如果你的NFT合约tokenId从1开始(不少ERC721合约采用这个规则),持有数量balance为N时,有效的tokenId是1到N。此时i < balance的条件会让循环只执行到i = N-1,漏掉最后一个NFT;如果balance = 1,循环条件直接不成立,导致循环跳过。

  2. 数字转换的潜在问题:
    用Number()转换合约返回的字符串余额虽然可行,但parseInt(xxx, 10)能更明确地指定十进制转换,避免一些隐式转换的异常情况。

  3. 缺乏错误处理:
    单个NFT的元数据请求失败会直接中断整个循环,没有容错机制。


修正后的代码

async getNFTMetadata() {
  try {
    // 稳妥转换余额为十进制数字
    const balanceStr = await contract.methods.balanceOf(this.currentUser.walletAddress).call();
    const balance = parseInt(balanceStr, 10);
    console.log("NFT余额:", balance, "类型:", typeof balance);

    // 根据你的合约tokenId起始规则选择循环逻辑
    // 情况1:tokenId从1开始(对应原代码逻辑)
    for (let i = 1; i <= balance; i++) {
      try {
        const tokenURI = await contract.methods.tokenURI(i).call();
        const response = await fetch(tokenURI);
        const metadata = await response.json();
        const imageUrl = metadata.image;
        console.log("第", i, "个NFT图片地址:", imageUrl);
        // 此处可将imageUrl存入数组,用于后续渲染图片网格
      } catch (err) {
        console.error("获取第", i, "个NFT元数据失败:", err);
      }
    }

    // 情况2:如果你的合约tokenId从0开始,启用下面的循环
    // for (let i = 0; i < balance; i++) {
    //   try {
    //     const tokenURI = await contract.methods.tokenURI(i).call();
    //     const response = await fetch(tokenURI);
    //     const metadata = await response.json();
    //     const imageUrl = metadata.image;
    //     console.log("第", i, "个NFT图片地址:", imageUrl);
    //   } catch (err) {
    //     console.error("获取第", i, "个NFT元数据失败:", err);
    //   }
    // }
  } catch (err) {
    console.error("获取NFT余额失败:", err);
  }
}

关键修改点

  1. 调整循环条件:

    • 若tokenId从1开始,循环条件改为i <= balance,确保遍历所有持有NFT;
    • 若tokenId从0开始,循环起始值设为0,条件用i < balance。
  2. 更可靠的数字转换:
    用parseInt(balanceStr, 10)替代Number(),明确指定十进制转换,避免字符串转数字的异常。

  3. 添加错误处理:
    两层try-catch分别处理余额获取失败和单个NFT元数据请求失败的情况,避免一处错误中断整个流程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 19:48:22