【问题标题】:Run The Build Synchronously同步运行构建
【发布时间】:2021-10-25 02:54:45
【问题描述】:

我的 for 循环无法同步运行。它为每个域返回的注册顺序发生了变化。我猜哪个答案最快的都会先带来这些记录。我哪里做错了?

const rrtypes= ["A","MX","CNAME","NS","TXT"];
var resData = [];
    
export const getAllRecords = async (req,res) => {
    const {domain} = req.params;
         for await(const rrtype of rrtypes){
             dns.resolve (domain, rrtype, (err, records) => { 
             resData.push(rrtype+" "+records);
        });
    }    
        res.send(resData);
        resData = [];      
}

【问题讨论】:

  • 如果要同步运行,不要使用async/await?还有never use for await … of on an array!
  • 您的意思是要按顺序运行循环吗?然后你需要promisifydns.resolve调用,await那个
  • 还要在你的函数声明中移动var resData = [];,否则数组将在多个调用之间共享。

标签: javascript node.js for-loop asynchronous async-await


【解决方案1】:

注意可以使用dns.promises.resolve函数:https://nodejs.org/api/dns.html#dns_dnspromises_resolve_hostname_rrtype

因此您将代码更改为:

const rrtypes = ["A", "MX", "CNAME", "NS", "TXT"];

export const getAllRecords = async (req, res) => {
  const { domain } = req.params;

  // Notice that resData should be local to this function
  let resData = [];
  for (const rrtype of rrtypes) {
    try {
      const records = await dns.promises.resolve(domain, rrtype);
      resData.push(rrtype + " " + records);
      // IMO this would be better: resData.push({ type: rrtype, value: records });
    } catch (err) {
      // Log the error here
    }
  }

  res.send(resData);
};

【讨论】:

    【解决方案2】:

    问题在于您使用await。调用异步函数时应使用await。目前,您在从数组中实例化变量时使用它。

    感谢 slebetman 的评论,我能够看到 dns.resolve 没有返回承诺,而是使用回调来管理异步调用。正如他还建议的那样,我们可以通过创建一个管理这些回调的承诺来解决这个问题。

    const rrtypes= ["A","MX","CNAME","NS","TXT"];
    var resData = [];
    
    const dnsResolvePromise = (domain, rrtype) => {
      return new Promise((resolve, reject) => {
        dns.resolve(domain, rrtype, (err, records) => { 
            if(err) return reject(err);
            resolve(rrtype+" "+records);
        });
      })
    }
    
    export const getAllRecords = async (req,res) => {
        const {domain} = req.params;
        for(const rrtype of rrtypes){
            try{
                const records = await dnsResolvePromise(domain, rrtype);
                resData.push(records);
           } catch (e){
             // Handle error
           }
        }    
        res.send(resData);
        resData = [];      
    }
    
    

    【讨论】:

    • 这是一个标准的 node.js 函数:nodejs.org/api/…。不,它不返回承诺。你必须向他展示如何将回调包装在 Promise 中
    • @slebetman 啊,感谢您向我指出这一点,我以前不知道。
    • 或者你可以使用已经内置的dns.promises.resolve,它使用promise而不是回调,所以你不需要辅助函数来将回调转换为promise
    • 这将使它们保持有序,但也会很慢,因为它会在运行下一个承诺之前等待每个承诺
    • @Dominic,没错,或者Promise.all 让它们并行
    猜你喜欢
    • 1970-01-01
    • 2011-12-31
    • 1970-01-01
    • 2012-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-02
    • 2016-12-29
    相关资源
    最近更新 更多