循环中等待Event Listener完成:dnsbl-lookup批量查询异常问题
解决批量DNSBL查询未等待完成就返回结果的问题
你的问题核心是dnsbl-lookup的事件驱动逻辑是异步的,但代码没有等待所有异步查询完成就直接返回响应,所以resultsArr始终是空的。要解决这个问题,需要把每个域名的查询逻辑包装成Promise,等待所有Promise执行完毕后再返回结果。
修改后的代码示例
const lookup = require("dnsbl-lookup"); const checkDomainsBlacklist = async (req, res, next) => { const errors = validationResult(req); if (!errors.isEmpty()) { return next(new HttpError("Invalid domain list", 422)); } const { domains } = req.body; // 封装单个域名的查询逻辑为Promise const checkSingleDomain = (domain) => { return new Promise((resolve) => { const domainResult = []; const targetDomain = domain.trim(); const dnsbl = new lookup.dnsbl(targetDomain, blockLists); dnsbl.on("error", (error, blocklist) => { console.log(`${targetDomain} 在 ${blocklist.zone} 查询出错:`, error); }); dnsbl.on("data", (result, blocklist) => { console.log(`${result.status} in ${blocklist.zone}`); if (result.status === "listed") { domainResult.push({ url: targetDomain, blUrl: blocklist.zone, }); } }); dnsbl.on("done", () => { console.log(`${targetDomain} 查询完成`); resolve(domainResult); // 查询完成时返回该域名的结果 }); }); }; // 生成所有域名的查询Promise数组,等待全部执行完成 const allResults = await Promise.all(domains.map(checkSingleDomain)); // 扁平化结果数组(单个域名可能命中多个黑名单) const resultsArr = allResults.flat(); res.status(200).json({ resultsArr }); // 所有查询完成后返回200状态码更合理 };
关键改动说明
- Promise封装单个查询:把每个域名的dnsbl查询逻辑放进Promise中,当
done事件触发时resolve该域名的查询结果,确保单个域名的查询流程完全结束后才标记为完成。 - Promise.all等待全部查询:用
Promise.all处理所有域名的查询Promise,只有当所有Promise都执行完成后,才会继续组装结果并返回响应。 - 结果扁平化处理:单个域名可能命中多个黑名单,用
flat()把二维结果数组转为一维,方便前端处理。 - 响应状态码调整:原代码用202表示请求已接受但未处理完成,现在所有查询都已完成,改用200状态码更符合语义。
内容的提问来源于stack exchange,提问作者J.Tran
相关产品推荐
相关产品推荐

