Node.js 无法理解异步/等待

Node.js 无法理解异步/等待,node.js,async-await,reverse-dns,Node.js,Async Await,Reverse Dns,我认为这是一个简单的例子。我想使用Express根据请求返回用户IP和主机名。但是从IP解析主机名给我带来了一点麻烦 router.get('/', (req, res) => { logRequest(req, res); }); async function logRequest(req, res) { res.send({ ip: req.ip, hostname: await getRemoteHostName(req.ip)

我认为这是一个简单的例子。我想使用Express根据请求返回用户IP和主机名。但是从IP解析主机名给我带来了一点麻烦

router.get('/', (req, res) => {
    logRequest(req, res);
});

async function logRequest(req, res) {
    res.send({
        ip: req.ip,
        hostname: await getRemoteHostName(req.ip)
    });
}

async function getRemoteHostName(ip) {
    await require('dns').reverse(ip, (err, domains) => {
        if (err) { handleError(err); return; }
        return domains.map(s => s.toLowerCase());
    });
}

我得到的只是我的IP
{IP:192.168.10.100}
,而我希望我也能得到我的主机名。如果I
console.log
my hostname,它会打印到控制台,但主机名不会在响应中由express发送回。我做错了什么?我觉得express在
dns之前发送了响应。reverse
可以完成查找,但我希望该查找完成,然后返回响应。

您将
回调
异步/等待

wait
应与
Promise

在您的情况下,
dns.reverse
不是一个承诺,不返回任何内容

首先,你需要使用

然后需要更新
getRemoteHostName
,以返回主机名并处理错误

const { Resolver } = require('dns').promises;
const resolver = new Resolver();

async function getRemoteHostName(ip) {
  try {
    const hostnames = await resolver.reverse(ip)
    // your logic here
    return hostnames
  } catch(error) {
    // handle error here
  }
}

对于节点v8.11.3,我需要推荐我的
getRemoteHostName()
方法

function getRemoteHostName(ip) {
  return new Promise((resolve, reject) => {
    require('dns').reverse(ip, (err, domains) => {
      if (err) { reject(err); }
      resolve(domains.map(d => d.toLowerCase()));
    });
  }).catch(error => {
    console.log(`error: ${error}`);
  });
}
之后,我用一个
async/await
像这样包装了我的
logRequest()

async function logRequest(req, res) {
  const client = {
    ip: req.ip,
    hostname: await getRemoteHostName(req.ip)
  };

  res.send(client);
}
在这一点上,我可以提出一个表达的要求

router.get('/', (req, res) => {
    logRequest(req, res);
});

并按预期获取我的主机名。

无需了解async/await即可实现此功能。你需要理解承诺
dns.reverse
不会返回承诺,因此无法等待。在我的
require('dns')…
之前,删除
wait
,并将其包装成
new Promise()
是你说的吗?没错。如答案所述,对于最后的节点版本,已经有了它的预期版本。因此,在较新版本的节点中,您不需要
…=要求(“dns”)。承诺
,只是
const{Resolver}=require('dns')链接的文档。。。是
11.0
。。。还有什么比这更新的?文档显示使用
.promises
废话,抱歉。我用的是v8.11。所以我需要把我的电话写在一封信里。没错,我不确定你到底需要为8.x做什么。看起来您可以对某些内容使用util.promsify,但使用
函数(err,data){return new Promise(…)}
类型的thing@CodyG. 你能再核对一下我在下面贴出的答案,看看这对你是否有意义吗?如果我遗漏了什么?去掉
.catch()
你正在吞咽错误,我个人会做
if(err){reject(err)}else{resolve(…)}
如果reject被传递给异步错误处理函数,你可能会遇到异步问题。。。resolve也会被调用,这似乎会抛出一些其他类型的奇怪错误,承诺只能被解决或拒绝一次,但我实际上不知道会发生什么。不过这是一个很好的问题资源,我同意。。。基本上,我不喜欢不使用
else
return
,因为您确实可以意外地运行代码。