在map函数中调用Promise,Promise.all执行后仍为pending状态的问题求助
问题分析与解决方法
嘿,我一眼就看出问题所在啦!你当前的代码里,Promise.all并没有真正等待那些余额查询的Promise完成——原因出在你用map生成的数组结构上。
问题根源
你写的temp.map(x => [x, self.getBalance(x)])会生成一个数组嵌套数组的结构,比如:
[ ['0x...', Promise { <pending> }], ['0x...', Promise { <pending> }] ]
而Promise.all的作用是等待数组里直接成员是Promise的对象完成。现在它看到的是一个个普通数组(不是Promise),所以直接把这些数组原样返回了,完全没去等待子数组里的Promise执行完毕。
修正方案(两种可选)
方案一:让每个map项返回一个Promise(推荐)
我们可以调整map的回调逻辑,让它返回一个Promise,这个Promise在余额查询完成后,会把「地址+余额」的数组作为结果resolve出来:
var prom = temp.map(x => // 先等待getBalance完成,再把地址和余额组合成数组 self.getBalance(x).then(balance => [x, balance]) ); Promise.all(prom).then(function(results) { console.log(results); // 这里的results会是类似:[['0x...', 2.5], ['0x...', 0.8]] }); // 建议给getBalance的catch补充返回值,避免Promise.all异常 getBalance(t){ return this.contract.methods.balanceOf(t).call() .then(function (result) { return result / Math.pow(10, 18); }) .catch(function(e) { console.log('error: '+e); // 可以返回0作为默认值,或者抛出错误让Promise.all处理失败 return 0; // 如果你想让Promise.all直接进入catch,就用:throw e; }); }
方案二:分开收集Promise再配对地址
如果你更习惯先分离地址和Promise,也可以先收集所有余额查询的Promise,完成后再和原始地址数组配对:
// 先收集所有余额查询的Promise const balancePromises = temp.map(x => self.getBalance(x)); Promise.all(balancePromises).then(balances => { // 将地址数组和余额数组一一对应组合 const results = temp.map((address, index) => [address, balances[index]]); console.log(results); });
额外注意
你的getBalance方法里的catch块如果只打印错误而不返回值或抛出错误,会导致该Promise以undefined作为结果resolve。建议补充默认值(比如0)或者重新抛出错误,这样能让Promise.all的结果更可控。
内容的提问来源于stack exchange,提问作者kasper Taeymans
相关产品推荐
相关产品推荐

