Node.js中Promise.all并发计算DeFi路由价格结果重复问题
并发调用价格计算函数时结果重复的排查与修复
核心问题定位
你遇到的并发结果覆盖问题,90%以上是共享可变状态导致的——多个并发调用的calc函数同时读写了同一个变量/对象,互相干扰。以下是具体排查方向和修复方案:
1. 检查calc函数内部的共享变量
如果calc里用了全局变量、闭包共享的对象/数组,并发时会被多个调用同时修改,最终返回的都是最后一次修改的值。
比如错误写法:
// 全局共享变量,并发时被覆盖 let tempData = {}; function calc(route) { tempData.route = route; tempData.price = calculateWithQuotes(tempData.route, quotes_5); return Promise.resolve(tempData.price); }
修复:把变量移到函数内部,每次调用创建独立实例:
function calc(route) { // 局部变量,每个调用独立 const tempData = { route: {...route} }; tempData.price = calculateWithQuotes(tempData.route, quotes_5); return Promise.resolve(tempData.price); }
2. 排查路由参数的引用共享
如果你的路由数组里的元素是同一个对象的引用,且calc内部修改了传入的route参数,并发时会互相覆盖对方的修改。
比如错误写法:
// 所有路由共享同一个baseRoute引用 const baseRoute = { pairs: [], exchange: '' }; const routes = [ baseRoute, // 直接引用 Object.assign(baseRoute, { exchange: 'SushiSwap' }) // 还是同一个引用 ];
修复:确保每个路由是独立对象,用深/浅拷贝隔离:
const routes = [ { pairs: ['ETH/USDC'], exchange: 'QuickSwap' }, { pairs: ['ETH/USDT'], exchange: 'SushiSwap' } ]; // 或者如果有基础模板,用拷贝生成 const baseRoute = { pairs: [] }; const routes = [ {...baseRoute, exchange: 'QuickSwap'}, {...baseRoute, exchange: 'SushiSwap'} ];
3. 检查quotes_5/quotes_2的可变状态
如果这两个变量是全局的,且在计算过程中被其他异步逻辑修改(比如同时更新报价),并发调用会拿到被篡改后的脏数据。
修复:调用calc时传入报价的快照,避免依赖全局可变变量:
// 每次调用时传入当前报价的副本 Promise.all(routes.map(route => { // 根据路由选择报价,生成快照 const quotes = route.type === '5' ? {...quotes_5} : {...quotes_2}; return calc(route, quotes); })); // 修改calc函数,使用传入的快照 function calc(route, quotes) { const price = calculateWithQuotes(route, quotes); return Promise.resolve(price); }
快速排查步骤
- 在
calc函数开头和结尾加日志,打印传入的route和计算出的price,看并发时参数是否被篡改; - 临时把
calc里的所有外部变量替换成局部变量,测试并发结果是否正常; - 用
console.dir打印路由对象的引用地址,确认每个路由都是独立的。
内容的提问来源于stack exchange,提问作者Dani
相关产品推荐
相关产品推荐

