如何在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) }
问题根源分析
循环条件不匹配:
原代码循环条件是i < Number(balance),但如果你的NFT合约tokenId从1开始(不少ERC721合约采用这个规则),持有数量balance为N时,有效的tokenId是1到N。此时i < balance的条件会让循环只执行到i = N-1,漏掉最后一个NFT;如果balance = 1,循环条件直接不成立,导致循环跳过。数字转换的潜在问题:
用Number()转换合约返回的字符串余额虽然可行,但parseInt(xxx, 10)能更明确地指定十进制转换,避免一些隐式转换的异常情况。缺乏错误处理:
单个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); } }
关键修改点
调整循环条件:
- 若
tokenId从1开始,循环条件改为i <= balance,确保遍历所有持有NFT; - 若
tokenId从0开始,循环起始值设为0,条件用i < balance。
- 若
更可靠的数字转换:
用parseInt(balanceStr, 10)替代Number(),明确指定十进制转换,避免字符串转数字的异常。添加错误处理:
两层try-catch分别处理余额获取失败和单个NFT元数据请求失败的情况,避免一处错误中断整个流程。
内容的提问来源于stack exchange,提问作者technosavvy
相关产品推荐
相关产品推荐

