Web3 BatchRequest调用execute始终返回undefined,该如何解决?
问题原因
你遇到的是web3.js版本差异导致的接口不兼容问题:
- 目前广泛使用的web3.js 1.x稳定版中,
BatchRequest.execute()确实是void类型,仅支持回调方式获取结果,不返回Promise,无法直接用async/await拿到返回值 - 你参考的教程使用的是web3.js 4.x开发版,该版本才新增了
execute()返回Promise的特性,和你本地安装的版本不匹配,才会出现返回undefined的情况
解决方案
提供两种兼容方案,可根据你的项目情况选择:
方案1:手动封装Promise(兼容1.x版本,无需升级依赖)
在添加批量请求时提前收集每个请求的Promise,执行batch后用Promise.all批量获取结果:
async generateContractFunctionList( address: Address, tokens: Token[], blockNumber: number ) { const batch = new this.web3.BatchRequest(); // 存储每个请求的Promise const balancePromises: Promise<string>[] = []; for (let i = 0; i < tokens.length; i++) { const contract = new this.web3.eth.Contract(balanceABI as AbiItem[]); contract.options.address = tokens[i].address; // 给每个请求绑定回调,包装为Promise const balancePromise = new Promise<string>((resolve, reject) => { batch.add( contract.methods .balanceOf(address.address) .call.request({}, blockNumber, (err: Error, result: string) => { if (err) return reject(err); resolve(result); }) ); }); balancePromises.push(balancePromise); } return { batch, balancePromises }; }
调用侧修改为:
async updateBalances() { try { const addresses = await this.addressService.find(); const tokens = await this.tokenService.find(); const blockNumber = await this.web3.eth.getBlockNumber(); for (let i = 0; i < addresses.length; i++) { const address = addresses[i]; const { batch, balancePromises } = await this.generateContractFunctionList(address, tokens, blockNumber); // 先执行批量请求 batch.execute(); // 等待所有请求返回结果 const balances = await Promise.all(balancePromises); console.log(balances); // 按请求顺序返回的所有代币余额数组 } } catch (error: unknown) { if (error instanceof Error) { console.log(`UpdateBalanceService updateBalances`, error.message); } } }
方案2:升级web3到4.x版本
web3.js 4.x正式版已支持BatchRequest.execute()直接返回Promise,升级后无需额外封装,直接await batch.execute()即可拿到批量请求结果,缺点是4.x存在较多破坏性更新,需要同步调整项目中其他web3相关的适配代码。
内容的提问来源于stack exchange,提问作者user16780074
相关产品推荐
相关产品推荐

