You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 17:50:35