异步函数场景下dns.resolve不等待forEach循环完成的问题如何解决
问题原因
- 你使用的是回调风格的
dns.resolveAPI,异步回调的执行逻辑不会被async/await捕获,forEach仅完成所有回调函数的注册就会结束执行,不会等待DNS解析结果返回 - 标记为
async的func1内部没有返回需要等待的Promise对象,外层的await func1()会直接进入完成状态,提前执行func2,此时resData还没有被解析结果填充,所以输出为空。
解决方案
你需要的并发执行所有DNS解析请求、无需各请求互相等待、等所有请求处理完成后再执行后续逻辑的需求,可以用Promise.all实现,推荐直接使用Node.js官方提供的Promise版本DNS API,修改后的代码如下:
const dns = require('dns').promises; const resData = []; // 此处替换为你实际的querys数组定义 const querys = []; const funcs = async() => { await func1(); await func2(); } const func1 = async() => { // 生成所有DNS解析的异步任务数组,所有请求会并发发起 const dnsTaskList = querys.map(async element => { try { const records = await dns.resolve(element.queryDomain, element.queryType); resData.push({ type: element.sendType, value: records }); } catch (err) { console.log('解析出错:', err); } }); // 等待所有解析任务全部执行完成 await Promise.all(dnsTaskList); } const func2 = async() => { console.log(resData); } funcs();
补充说明
- 所有DNS解析请求会同时发起,不会等待前一个解析完成才发起下一个,完全符合你要求的各条解析记录无需互相等待的逻辑
- 单个解析请求出错只会打印日志,不会中断其他解析请求的执行,所有请求处理完成后才会执行
func2,此时resData已经填充了所有成功的解析结果
如果你坚持要使用回调风格的
dns.resolve,可以用util.promisify手动转换为Promise风格后再按上述逻辑实现:const { promisify } = require('util'); const dnsResolve = promisify(require('dns').resolve);
内容的提问来源于stack exchange,提问作者aliveli49
相关产品推荐
相关产品推荐

