如何用Node.js异步批量检查100个站点的状态、内容及MX记录?
批量站点检测的Promise实现方案
核心思路
把单个站点的所有检测逻辑封装为独立的Promise函数,再通过Promise.allSettled(或Promise.all)并行执行所有站点的检测任务,彻底解决同步处理的性能瓶颈。
分步实现
1. 封装单个站点的检测逻辑
每个站点需要完成HTTP可用性+响应体校验、MX记录查询两个独立任务,我们可以并行执行这两个任务,最大化效率。
以下是基于Node.js环境的示例代码(浏览器环境可将HTTP请求替换为fetch):
const http = require('http'); const https = require('https'); const dns = require('dns').promises; // 检查站点可用性+响应体内容 function checkSiteAndContent(url, expectedContent) { return new Promise((resolve) => { const client = url.startsWith('https') ? https : http; client.get(url, { timeout: 5000 }, (res) => { const isReachable = res.statusCode >= 200 && res.statusCode < 400; let responseBody = ''; res.on('data', (chunk) => responseBody += chunk); res.on('end', () => { const contentValid = isReachable ? responseBody.includes(expectedContent) : false; resolve({ url, isReachable, contentValid, statusCode: res.statusCode }); }); }) .on('error', (err) => resolve({ url, isReachable: false, contentValid: false, error: err.message })) .on('timeout', () => resolve({ url, isReachable: false, contentValid: false, error: '请求超时' })); }); } // 查询域名MX记录 async function checkMxRecord(domain) { try { const mxRecords = await dns.resolveMx(domain); return { domain, success: true, records: mxRecords.map(r => `${r.exchange} (优先级: ${r.priority})`) }; } catch (err) { return { domain, success: false, error: err.message }; } } // 单个站点的完整检测流程 async function checkSingleSite(siteInfo) { const { url, expectedContent, domain = new URL(url).hostname } = siteInfo; // 并行执行两项检测任务 const [httpResult, mxResult] = await Promise.all([ checkSiteAndContent(url, expectedContent), checkMxRecord(domain) ]); return { site: url, http: httpResult, mx: mxResult }; }
2. 批量处理所有站点
将100个站点的信息整理为数组,通过Promise.allSettled并行执行检测:
// 示例站点数组:每个元素包含url、要校验的内容,域名可选(默认取url的hostname) const sites = [ { url: 'http://example.com', expectedContent: 'Example Domain' }, { url: 'https://google.com', expectedContent: 'Google' }, // ... 剩余98个站点 ]; // 批量执行检测 async function batchCheckSites(sites) { // 生成所有单个站点检测的Promise数组 const checkPromises = sites.map(site => checkSingleSite(site)); // 等待所有任务完成(无论成功失败) const results = await Promise.allSettled(checkPromises); // 整理最终结果 return results.map((result, index) => { const targetSite = sites[index]; if (result.status === 'fulfilled') { return { site: targetSite.url, success: true, data: result.value }; } else { return { site: targetSite.url, success: false, error: result.reason.message }; } }); } // 执行并处理结果 batchCheckSites(sites) .then(finalResults => { console.log('批量检测完成:', finalResults); // 可按需统计:可用站点数、MX记录正常数等 }) .catch(err => console.error('全局错误:', err));
3. 关键细节说明
Promise.allSettled的优势:不同于Promise.all(单个失败则全局reject),它会等待所有任务完成,适合需要完整结果集合的场景。- 并行执行效率:同步处理耗时是所有请求时间的总和,并行处理仅耗时最长的单个请求时间(忽略网络排队限制),效率提升显著。
- 超时与错误隔离:每个子任务单独处理错误和超时,避免单个异常拖垮整个批量任务。
扩展优化
- 并发数限制:直接并行100个请求可能触发限流,可通过工具(如
p-limit)或自行实现控制并发数。 - 结果持久化:将检测结果写入文件或数据库,方便后续分析。
- 实时进度:检测过程中打印完成进度,提升可视化体验。
内容的提问来源于stack exchange,提问作者Jack27696
相关产品推荐
相关产品推荐

