Promise在forEach循环后无法获取异步调用结果的问题排查
问题分析与解决方案
我明白你遇到的问题了——这是Promise新手常踩的异步时序坑!你的代码里,resolve(holdings)是在bittrex.getbalances的回调里直接执行的,但此时所有bittrex.getticker的异步请求还没完成,所以holdings还是空数组。而setTimeout只是靠延迟让异步请求碰巧完成,这完全是不可靠的“玄学修复”,我们得用Promise的正确方式来等待所有异步操作结束。
核心问题
你的Promise没有等待内部的getticker异步调用完成就提前resolve了。bittrex.getbalances和bittrex.getticker都是回调式的异步API,你需要把它们都Promise化,然后用Promise.all来等待所有异步任务结束后再返回结果。
修正后的代码
const bittrex = require('node.bittrex.api'); const { key, secret } = require('./key'); // 先把回调式的bittrex方法包装成Promise const getBalancesPromise = () => { return new Promise((resolve, reject) => { bittrex.getbalances((data, err) => { if (err) reject(err); else resolve(data.result); }); }); }; const getTickerPromise = (market) => { return new Promise((resolve, reject) => { bittrex.getticker({ market }, (ticker, err) => { if (err) reject(err); else resolve(ticker.result.Last); }); }); }; // 主逻辑:用Promise.all等待所有异步任务 const getBalance = async () => { const balances = await getBalancesPromise(); // 过滤出余额不为0的币种,同时生成对应的Promise数组 const tickerPromises = balances .filter(coin => coin.Balance !== 0) .map(async (coin) => { const market = coin.Currency === 'BTC' ? 'USDT-BTC' : `BTC-${coin.Currency}`; const lastPrice = await getTickerPromise(market); return { Coin: coin.Currency, Balance: coin.Balance, Last: lastPrice }; }); // 等待所有ticker请求完成,得到最终的holdings数组 return Promise.all(tickerPromises); }; // 调用并输出结果 getBalance() .then((holdings) => { console.log(holdings); }) .catch((err) => { console.error('出错了:', err); });
关键改动说明
- Promise化回调API:把
getbalances和getticker分别包装成返回Promise的函数,这样就能用await或者Promise.then来等待异步结果。 - 使用
async/await简化逻辑:主函数用async声明,内部用await等待余额请求完成,再对每个符合条件的币种发起ticker请求。 Promise.all等待所有异步任务:map返回的是一个Promise数组,Promise.all会等待所有Promise都resolve后,返回一个包含所有结果的数组,这时候的holdings就是完整的结果了。- 错误处理:新增了
catch块来捕获整个流程中的错误,避免未处理的Promise rejection。
这样修改后,就不需要依赖setTimeout了,能可靠地等待所有异步网络请求完成后再返回正确的holdings数组。
内容的提问来源于stack exchange,提问作者Caruso33
相关产品推荐
相关产品推荐

