VeilSwap
← 全部文章
指南2026-11-068 分钟阅读

弱网下的兑换页:3G 上到底哪里会坏(2026 实测)

Slow 3G 下兑换页 1.6 秒就「看起来能用」,真正可用却要等到 6.8 秒。实测:早期输入会被清空、慢慢打字会触发四次报价、乱序响应能把显示价格翻掉。

2026-11-06 14:03 UTC,我用全新的移动端 Chromium 配置打开 veilswap.io/exchange,网络限成 Chrome 的 Slow 3G(往返 400ms、上下行各 400kbps),记录每个请求。输入框 1.6 秒可见,但第一个数据请求 /api/currencies 到 6.84 秒才发出——React 到那时才接管。这中间 40 个请求搬了 235KB;最大的三个 JS chunk(54.7、47.0、28.2KB)光下载就花了 6.09、5.91、5.04 秒。报价响应体 181 字节,接口本身 0.44–1.10 秒——定价从来不是瓶颈。不设限速时第一个请求 0.589 秒就发出。弱网下页面慢,是因为它重。

失败一:表单先出现,后才有生命。 我在 1.93 秒输入 100,此时服务端 HTML 已在屏幕上,JS 还在下载。到 15 秒,输入框是空的,报价请求为 0。hydration 用 React 的初始状态(空字符串)覆盖了 DOM 值,输入就这样消失,没有报错。这不是 React 的 bug,而是「表单写在 HTML、状态写在 JS」的 hydration 必然结果。快网第一个请求 0.589 秒发出,Slow 3G 6.84 秒。规则:等币种数量或汇率出现再输入;值没了就重打。

失败二:500ms 防抖只对打得快的人有效。 代码在最后一次按键后等 500ms 再发 /api/quote。一次 fill 100 只发 1 个请求,1.49 秒后显示到账额。按每字符 900ms 打「1000」发了 4 个请求:amount=1 在 +0.51 秒、10 在 +1.42 秒、100 在 +2.32 秒、1000 在 +3.23 秒,最多两个同时在飞;前两个返回 400,因为 1、10 USDT 低于该币对 19.219061 的下限。每次往返 0.7–1.1 秒。报价接口每 IP 每 10 分钟 60 次,且在参数校验前计数,约 15 次慢速编辑就能耗尽。8 秒缓存的键是 from|to|amount:同一笔 100 USDT-TRX 在 5 秒内重复,240–295ms 返回同一份 181 字节响应;金额改一分钱就 miss。 (XMR 换 USDT 退出路线)

失败三:响应会乱序,旧的可能后到并覆盖新的。 报价 effect 没有 AbortController,也没有请求序号,每个响应都直接 setQuote。14:07 UTC 用两份真实报价(100 USDT→0.14082928 XMR;1,000→1.592011),把第一份延迟 2.5 秒、第二份延迟 0.1 秒。先输 100 再输 1,000,屏幕停在 0.140829,输入框是 1,000——少显示 11.3 倍。反过来延迟,输入 100 时到账行显示 1.592,汇率行 0.00159183,而正确的是 0.00140888,高 13.0%。下单接口会重新报价并按请求金额建单,所以不会按旧价成交——但用户看到的屏幕是错的。等汇率稳定,或下单前刷新。 (XMR 换 USDT 退出路线)

失败四:订单页每 5 秒轮询,没有超时,也没有在途保护。 代码先请求 /api/order/<id>,再 setInterval(5000);每次独立,没有 AbortController,也不会「上一发没回来就跳过这一拍」。我让第一次响应 0.5 秒返回 waiting_deposit,之后全部挂住:请求出现在 1.6、7.1、12.1、17.1、22.1、27.1、32.1 秒——正好每 5.000 秒——最后同时有 6 个在飞。页面一直显示「等待充值」,琥珀色的「状态同步延迟」横幅没出现,因为它只在上游返回 pollError 时设置,fetch 挂住或非 2xx 都不触发。手机后台标签页还会进一步节流。订单本身不依赖这个页面:入金地址在池方,出金按池方的时钟走。

失败五:重试的账比看上去贵。 Exchange 按钮在 creating 为 true 时禁用,但 click handler 没有第二道判断。真正的墙在服务端:同一 IP、同样 fromAsset|toAsset|fromAmount|toAddress,90 秒内重复,会在调用任何池子前返回 429 duplicate order。14:06 UTC 用一笔故意低于下限的 1 USDT 单实测:第一次 POST 1.128 秒返回 400 amount below minimum(下限 19.219061、上限 165,135.014302);完全相同的第二次 0.234 秒返回 429 duplicate order。便宜、正确。不便宜的是:每 IP 6 单/小时的限流器跑在字段和地址校验之前,每次失败都烧掉一个名额;退款地址打错 6 次,接下来一小时可能下不了真单。地址在表单里改;看到 duplicate order,打开订单链接,别改金额硬造第二单。 (转错网络如何找回)

3G 上该怎么做,页面该改什么。 用户侧:等币种数量或汇率出现再输入;链路慢就粘贴金额;每次改完,等到账行不再跳动,并核对「1 USDT ≈」的汇率是否匹配;转圈超过 10 秒当成「还没好」,不是「失败」;记住订单链接,但别把订单标签页开一小时。页面侧:防抖按 RTT 自适应;上一笔报价 abort 并忽略乱序响应;71KB 币种目录现在被两个组件各取一次(压缩后每次 13.9KB),合并成一次;缩小卡住 hydration 的首屏 bundle;轮询加超时、退避和 visibilitychange 立即刷新;hydration 完成前禁用表单。 (XMR 换 USDT 退出路线)

收尾:兑换活得下来,屏幕才是弱点。 免 KYC 兑换的主体是一个地址和一笔入金:钱在池方,按池方的时钟出款,链路再差也取消不了已建好的订单。它能做的是显示错数、吞掉输入、让你点两次。截至写作时(2026-11-06 14:0x UTC),100 USDT-TRX 报 0.14082928 XMR(1 条路由,validUntil 120 秒),1,000 报 1.592011 XMR(2 条路由);同一币对下限 19.219061、上限 165,135.014302;目录 436 种资产、65 条网络。数字会动,以页面实时报价为准。 (XMR 换 USDT 退出路线)

常见问题

刚打开页面时输入的金额,为什么会自己消失?

因为表单是服务端渲染的 HTML,状态却住在 JavaScript 里。2026-11-06 的 Slow 3G 实测:输入框 1.6 秒可见,第一个数据请求 6.84 秒发出,React 6.84 秒才接管;1.93 秒输入的值到 15 秒时已为空,报价请求 0 次。等币种数量或汇率出现再输入;如果值已经没了,页面稳定后重打。

弱网下输入一个金额,会花掉几次报价请求?

粘贴金额、或者每字符快于 500ms 时,只花 1 次;按每字符 900ms 打「1000」会花 4 次(金额 1、10、100、1000),最多两个同时在飞。报价接口每 IP 每 10 分钟只给 60 次,而且在参数校验之前就计数,所以大约 15 次慢速编辑就能耗尽。8 秒缓存只在币对和金额完全相同时才有效。

弱网会让屏幕上的价格变成错的吗?

会。报价的 effect 没有 abort,也没有请求序号,慢的旧响应可以覆盖新响应。14:07 UTC 用两份真实报价、把响应分别延迟 2.5 秒和 0.1 秒:输入 100 时显示 1.592 XMR(高 11.3 倍),汇率行比正确值高 13.0%。下单接口会重新报价并按请求里的金额建单,所以不会按旧价成交——但屏幕是错的。等汇率稳定,或者下单前刷新。

继续阅读

全部文章 →

准备好换币了吗?

无账户 · 无 KYC · 无邮箱

立即兑换
弱网下的兑换页:3G 上到底哪里会坏(2026 实测) — VeilSwap