Node.js使用dns.resolve查询时for循环无法同步执行,域名解析记录返回顺序混乱排查
问题根因
- 误用
for await...of语法:该语法仅适用于遍历异步迭代器,你的rrtypes是普通字符串数组,循环会瞬间执行完毕,不会等待内部的DNS解析操作完成,执行到res.send时大部分解析请求还没返回结果,resData要么为空要么内容不全。 dns.resolve是回调式异步API,本身不支持Promise和await:解析操作的回调触发时机完全依赖DNS服务器的响应速度,哪条解析请求先返回就先往resData里插入数据,自然顺序不固定。- 全局
resData变量存在严重并发问题:多个用户同时调用接口时,不同请求的解析结果会互相写入同一个全局变量,导致返回内容错乱。
修复代码
以下是并发执行+保持原顺序的高性能修复方案:
const dns = require('dns').promises; // 直接使用dns模块自带的Promise版本API const rrtypes= ["A","MX","CNAME","NS","TXT"]; export const getAllRecords = async (req,res) => { const {domain} = req.params; try { // 并发发起所有解析请求,全部完成后按rrtypes的原始顺序返回结果 const resList = await Promise.all( rrtypes.map(async (rrtype) => { try { const records = await dns.resolve(domain, rrtype); return `${rrtype} ${records}`; } catch (err) { // 单条解析类型无记录时返回提示,避免整个请求失败 return `${rrtype} 无解析记录`; } }) ); res.send(resList); } catch (err) { res.status(500).send('域名解析失败'); } }
修复说明
- 替换为Promise版本的dns API,直接支持await语法,无需手动封装回调转Promise
- 用
Promise.all并发发起所有解析请求,所有请求完成后会严格按照rrtypes的原始顺序返回结果,既保证顺序又比逐个等待解析的性能更高 - 移除全局
resData变量,改用请求级别的局部变量存储结果,避免多请求并发时的数据冲突 - 增加异常捕获逻辑,避免某一条解析类型无记录或者报错导致整个接口崩溃
内容的提问来源于stack exchange,提问作者aliveli49
相关产品推荐
相关产品推荐

