Repository Wiki
jason5ng32/MyIP

站点连通性、延迟与测试列表

站点连通性面板使用浏览器 fetch 探测当前测试列表中的目标,并展示可达状态、请求耗时及多轮测试记录。它同时提供列表切换、单卡重测和目标删除入口,通过领域事件把最新测试快照交给其他功能使用。

目的与范围

本页覆盖 ConnectivityTest 的界面入口、活动列表选择、单次探测、批次汇总、多轮最佳结果语义、通知门控与并发保护。重点回答“页面上的可用、不可用和毫秒数究竟如何产生”。

以下内容不在本页展开:ASN 网络互联、Globalping 全球延迟、MTR、DNS/WebRTC 检测,以及报告页面的最终渲染。它们不能与这里的浏览器直连探测混为一谈。

**证据边界:**本文基于 ConnectivityTest.vue 与其 探测和汇总代码。列表导入工具、偏好存储实现、组件中间的状态转换辅助函数和启动函数末尾未在本次阅读范围内,因此不推断其校验规则、存储介质、轮次间隔或卸载清理行为。

概述

该面板有三个不同的操作层级:

层级入口实际作用
测试列表列表菜单调用 switchList(list.id)切换本次访问使用的活动列表
整体测试周期刷新按钮调用 handelCheckStart('manual')开始新一代测试,区分通知和重置策略
单个目标毫秒按钮或失败重试按钮调用 checkConnectivityHandler(test, () => { }, true)

多轮模式采用 best-of-N(保留最佳成功结果),不是平均延迟,也不是必须每轮都成功。卡片主状态和逐轮记录因此可能不同:卡片仍显示可用,某次轮次记录却是失败。

这里的“延迟”是 performance.now() 测得的 fetch Promise 完成耗时,不是 ICMP RTT,也不是完整页面加载耗时。源码不读取响应正文、不检查 HTTP 状态码;Promise 正常完成即进入可用分支。

来源:界面入口、计时与结果处理。

架构与数据流

Loading diagram...

Source: ConnectivityTest.vue、ConnectivityTest.vue

列表配置来自 store.userPreferences;运行结果保存在组件的目标状态中。删除目标通过 store.updatePreference 回写配置,而测试汇总通过 connectivity:finished 事件输出。已读探测路径由浏览器直接请求目标,没有调用项目后端代理端点。

图中仅展示已核实的关系;handelCheckStart 后半段的调度实现不在已读范围内,不能据此补画完整轮次调度链路。

测试列表与卡片交互

活动列表选择

lists 读取 userPreferences.connectivityLists?.lists,配置缺失时使用空数组。初始化选择逻辑是:优先采用 connectivityDefaultListId;只有该 ID 存在于列表集合中才接受,否则回退到 MINE_LIST_ID。

javascript
1const initialListId = () => { 2 const preferred = userPreferences.value.connectivityDefaultListId; 3 return lists.value.some((l) => l.id === preferred) ? preferred : MINE_LIST_ID; 4}; 5const activeListId = ref(initialListId()); 6const activeList = computed(() => lists.value.find((l) => l.id === activeListId.value));

Source: ConnectivityTest.vue

switchList(id) 在 ID 未变时直接返回;否则更新本地 activeListId 并记录分析事件,没有在该函数内修改默认列表偏好。源码注释明确区分“本次访问切换”和“首选默认列表”。集合变化时,若活动列表已被删除,监听器再次回退到 MINE_LIST_ID。注意,这个回退逻辑本身不创建缺失的 Mine 列表。

只有 lists.length > 1 时才显示列表选择菜单。菜单的管理入口调用 openAddDialog('lists');添加测试卡片调用 openAddDialog('import')。对话框接收 open、initial-tab、active-list-id,具体导入格式及合并策略尚未核实。

来源:列表菜单、对话框入口、活动列表逻辑。

卡片展示与重测

  • 卡片标题是否为链接由 connectivityCardTitleOpensSite 与 siteUrlOf(test) 共同决定;无法获得地址或偏好关闭时渲染为普通容器。
  • 外链使用 _blank 和 noopener noreferrer。
  • 图标加载失败时设置 faviconFailed,随后显示名称首字母;图标加载成功不参与站点可用性判定。
  • 非零 test.time 显示为可点击毫秒数;当 time === 0 且状态为失败时显示重试图标。
  • 两种重测入口均传入 isManualRun = true,因此不会追加多轮历史。
  • 多轮模式显示 totalRounds 个记录位置。可见初始化为 maxCounts = 9、totalRounds = 1 + maxCounts,即 10 个位置;实际调度间隔不在已核实范围内。

来源:卡片模板、轮次数状态。

两步删除与配置回写

删除先进入确认态,第二次点击相同目标才删除;确认态在 3000 ms 后自动解除。Mine 列表仅剩一个目标时,直接提示警告,不允许删空。注释说明其他列表允许清空,但是否能删除列表由其他实现负责。

removeTargetById 调用 removeMember(lists.value, activeListId.value, id);返回结果包含 error 时直接退出,否则通过 store.updatePreference('connectivityLists', ...) 保存替换后的列表集合。这里只能确认偏好更新边界,不能据此断言使用 localStorage、数据库或服务端同步。

来源:删除实现。

探测机制与延迟语义

请求方式与超时

以下为实际探测代码节选:

javascript
1const controller = new AbortController(); 2const timeoutId = setTimeout(() => controller.abort(), 3 * 1200); 3const beginTime = performance.now(); 4try { 5 await fetch(test.url, { 6 mode: 'no-cors', 7 method: 'GET', 8 cache: 'no-store', 9 signal: controller.signal, 10 });

Source: ConnectivityTest.vue

源码明确说明选择 no-cors GET 是为了避免 HEAD 或图片探测将可达站点误判为不可达;cache: 'no-store' 用于减少缓存造成的近零耗时。超时阈值为 3600 ms,通过 AbortController.abort() 令请求进入失败处理。

成功和异常路径都会清理超时定时器。由于没有检查 response.ok 或状态码,本模块判定的是该请求是否完成,而不是目标业务是否健康。所有异常统一进入相同的失败分支,界面不区分超时、网络错误或浏览器阻止请求。

最佳结果与逐轮历史

recordRound = multipleTests.value && !isManualRun 决定是否参与多轮聚合。成功时耗时四舍五入到整数毫秒,并同步写入本地化 status 和不依赖语言的 statusCode。

javascript
1test.statusCode = CONNECTIVITY_STATUS.OK; 2test.mintime = test.mintime === 0 ? testTime : Math.min(test.mintime, testTime); 3test.time = recordRound ? test.mintime : testTime; 4if (recordRound) test.roundResults.push({ tone: testTime < 200 ? 'ok-fast' : 'ok-slow', time: testTime }); 5onTestComplete(true);

Source: ConnectivityTest.vue

数据含义
time卡片当前显示值;多轮聚合时取最佳值,否则取本次成功耗时
mintime成功结果中的最小耗时;代码用 0 表示尚无有效最小值
roundResults每次完成时追加的 { tone, time } 记录
status本地化状态文案
statusCodeCONNECTIVITY_STATUS.OK 或 UNREACHABLE;尚未判定时可为 undefined

成功耗时 < 200 ms 记录为 ok-fast,否则为 ok-slow;这是一条显示分类阈值,不是超时阈值。

多轮失败时,若 mintime > 0,卡片继续保持可用及最佳时间,但追加 { tone: 'fail', time: 0 }。否则清零显示时间并标记 UNREACHABLE。因此某一轮的失败不会抹去本周期已经取得的成功结果。

来源:成功与失败分支。

批次执行、事件与通知

批次执行顺序

checkAllConnectivity(isAlertToShow, isRefresh, isManualRun) 返回一个等待批次汇总的 Promise:

  1. 仅当 isAlertToShow 为真时将 alertToShow 置真,后续轮次传入假不会覆盖已经启用的通知意图。
  2. 增加 passSeq,将当前批次标识保存为 passId。
  3. 如果 isRefresh 为真,清除所有卡片的 statusCode 并把 time 置零;此处没有清除 mintime。
  4. 对尚无 statusCode 的卡片设置“测试中”文案;已有结论的卡片在后续多轮批次启动时保持原判定。
  5. 快照当前目标 ID 集合,按 50 * index ms 错峰启动各目标请求。
  6. 通过 Promise.allSettled 等待成功与失败请求全部完成,避免单个失败使整批提前退出。
  7. 如果当前批次已经过时,仅兑现外层 Promise;否则汇总当前仍存在且属于本次调度集合的已判定卡片。
  8. 更新通知内容、设置 hasEverSettled = true,并发送整个当前网格的结果快照。
Loading diagram...

Source: ConnectivityTest.vue

快照协议

事件载荷来自实际代码,可作为报告或其他消费者的集成参考:

javascript
1emitAppEvent('connectivity:finished', { 2 targets: connectivityTests.map((test) => ({ 3 id: test.id, 4 name: test.name, 5 custom: test.id.startsWith('custom-'), 6 statusCode: test.statusCode, 7 time: test.time, 8 mintime: test.mintime, 9 })), 10});

Source: ConnectivityTest.vue

事件不是“本批新增结果”列表,而是完整网格的最新快照。它不包含 url、本地化 status 或 roundResults。custom 通过 ID 的 custom- 前缀判断,并非单独从目标配置读取。

批次通知与快照的范围刻意不同:通知只判断该批调度过、完成时仍在网格中且已有状态码的目标;快照输出全部当前卡片。这样,批次中途添加的卡片不会被错误地算成本批失败,中途删除的卡片也不会拖累剩余卡片的汇总结果。

通知门控与入口差异

sendAlert() 同时检查以下条件:尚未发送过、autoShowAltert 开启、alertToShow 已启用、store.allHasLoaded 为真、allRoundsDone 为真。通过后先设置 alertFired,再调用 store.setAlert。通知内容的计算与实际弹出因此是两个步骤。

finalizeMultiTestAlert() 按 mintime > 0 统计至少成功过一次的目标;当数量等于当前目标总数时选择成功通知,而不是要求所有历史轮次都成功。

handelCheckStart 的 trigger是否允许本周期通知是否要求重置卡片语义
boot(默认)是否启动自动测试
manual是是面板整体刷新
refresh否是全局刷新及列表切换场景

这里的 manual 触发整个周期,与单卡调用传入 isManualRun = true 不是同一层概念。源码注释说明多轮偏好适用于全部三种周期入口,不仅是启动测试。已读启动函数还会增加 runSeq,并在多轮模式下清除已有 interval、重置计数及完成标记;后续如何启动和结束全部轮次尚未核实。

来源:通知条件和文案、最终聚合与启动策略。

配置选项与内部常量

下表区分“组件读取的用户偏好”和“组件内部确定的数值”。偏好的全局默认值不在已读源码中,不能把组件读取行为写成配置默认值。

选项使用类型默认值或回退作用
connectivityLists包含 lists 的对象读取不到列表时使用 []测试列表集合
connectivityDefaultListId列表 ID无匹配时使用 MINE_LIST_ID初始活动列表
connectivityMultipleTests布尔用途全局默认值未核实挂载时快照到 multipleTests,更改在下次重新加载应用
popupConnectivityNotifications布尔用途全局默认值未核实初始化 autoShowAltert,控制完成通知
connectivityCardTitleOpensSite布尔用途全局默认值未核实控制标题是否可打开网站
simpleMode布尔用途全局默认值未核实简洁模式隐藏说明文字
请求超时数值常量3600 ms中止单次请求
目标错峰数值表达式50 * index ms分散同批目标的启动时间
快慢分类阈值数值常量200 ms< 200 为 ok-fast
maxCounts / totalRounds数值状态 / 计算值9 / 10多轮计数及历史显示位置
删除确认窗口数值常量3000 ms自动解除确认态

来源:偏好读取、超时和分类、错峰调度、删除确认。

内部接口参考

这些函数位于 Vue <script setup> 中,是组件内部接口,不是后端 HTTP API。源码为 JavaScript,没有声明静态参数类型。

实际签名参数与返回行为
checkConnectivityHandler(test, onTestComplete = () => { }, isManualRun)async 函数;test 为可变目标状态,回调接收成功布尔值,isManualRun 决定是否跳过轮次历史;正常完成无业务返回值
checkAllConnectivity(isAlertToShow, isRefresh, isManualRun)参数依次控制通知启用、卡片刷新和探测模式;返回批次结束时兑现的 Promise,无结果载荷
handelCheckStart(trigger = 'boot')async 周期入口,已核实代次更新与触发策略;末尾等待和完成行为未核实
switchList(id)更新本地活动列表并记录分析事件;相同 ID 不处理,无显式返回值
openAddDialog(tab)设置初始 tab 并打开对话框,无显式返回值
removeTargetById(id)删除成员并回写偏好;工具返回 error 时直接退出
handleRemoveClick(id)执行 Mine 最后一个成员保护及两次点击确认
sendAlert()通过所有门控才发送通知;无显式返回值
finalizeMultiTestAlert()根据当前目标是否都曾成功更新通知内容,不直接弹出

探测请求的拒绝和超时在 checkConnectivityHandler 中被捕获,并通过回调转换为失败结果;checkAllConnectivity 使用 allSettled,不会因一个正常的探测失败而走整批快速拒绝。其他依赖(如偏好写入工具)是否抛出异常,未从其实现核实。

来源:探测与批次函数、管理与通知函数。

并发保护、边界与故障解释

两级代次保护

  • runSeq 保护跨周期结果写入。 handelCheckStart 增加代次;单次处理器开始时捕获 runId。请求结束后若代次不同,不更新卡片,但仍调用完成回调,使旧批次可以结束。
  • passSeq 保护批次汇总。 每次 checkAllConnectivity 增加批次号。过期批次在 allSettled 后仅兑现 Promise,不更新通知、不发结果事件。
  • 同一周期内允许轮次重叠。 源码明确允许慢请求在下一轮开始后继续写结果,因此跨轮并不采用逐目标“最新请求覆盖一切”的序列锁。
  • 忽略结果不等于取消请求。 runSeq 检查发生在请求完成或异常之后;可见代码没有集中保存所有控制器并在换周期时立即取消它们。

单卡重测没有独立的目标版本号。若同一周期内对同一个目标重复点击,已读处理器没有防重入判断,多个请求可同时修改同一个目标。多轮历史通过 push 在完成时追加,没有显式轮次索引,所以不能把记录位置无条件解释为严格的请求启动顺序。

来源:并发设计注释与处理器、批次过期检查。

需要注意的边界

场景可见实现行为解读注意
超时或任意请求异常进入同一失败分支不能仅凭卡片定位具体网络故障
多轮已有成功后再失败保留 OK 和 mintime,记录失败轮次主卡片不是最后一轮状态
单卡重测失败设置 time = 0、UNREACHABLE,不清除 mintime当前结果与历史最佳值可以不同
耗时四舍五入为 0成功时可写入 OK,但 mintime > 0 不成立0 同时承担哨兵值,极小耗时存在语义边界
批次汇总对象为空finished.every(...) 返回真成功通知不必然代表实际测到了至少一个目标
当前网格为空多轮统计得到 0 === 0最终聚合也可能选择成功文案
批次中途增删目标通知基于调度 ID 与当前网格交集;事件基于整个网格事件内容与本批判定集合不完全相同

这些边界均可从 结果更新、汇总过滤 和 多轮统计 推导;它们不是新增的产品保证。

性能、运维与扩展建议

请求规模。 每个批次为每个目标建立一次定时任务和一个请求 Promise。50 ms 错峰不是并发上限;目标越多,最后一个目标越晚开始。单卡重测还可额外增加请求。不要仅用 3600 ms 超时推断整批固定在 3.6 秒内结束。

诊断顺序。 排查某个站点时,先确认活动列表和实际 test.url,再看浏览器请求是否完成或被中止;确认是在单卡模式还是多轮最佳值模式;最后检查是否发生换周期、批次过期或通知门控未通过。不要用图标是否加载或主卡片是否保留绿色替代请求结果检查。

扩展位置。 若需要区分超时与其他错误,应从处理器的 catch 分支和状态协议同步扩展;若需要严格按轮次展示历史,应引入明确的轮次标识,而不能只依赖完成时 push。若增加报告字段,应在 connectivity:finished 载荷与消费者之间共同约定,不要依赖本地化 status 反推状态。

这些是依据现有控制流给出的工程建议,不代表仓库已经实现了相关扩展。列表导入、安全校验、偏好持久化和卸载清理需要进一步阅读对应实现。本次未读取相关测试正文,因此不声明上述边界已有自动化测试覆盖。

相关链接

本次运行时没有提供其他目录页的实际路径,因此不构造未经核实的 Wiki 跳转链接。全球延迟、ASN、DNS/WebRTC 和报告渲染应查阅各自主题文档,而不是套用本页的浏览器请求语义。

Sources

(1 files)