【问题标题】:Problem when using async-await block inside .then() block in javascript-nodejs在 javascript-nodejs 中的 .then() 块中使用 async-await 块时出现问题
【发布时间】:2022-01-23 15:33:12
【问题描述】:

问题
我使用 ipManager 作为中间件。但由于某种原因,相同的 json 对象被添加到 firestore 两次。此外,还有许多其他行正在重复。

代码:

//imports...
exports.ipManager = (req, res, next) => {
  const ip = req.clientIp;
  const fullUrl = req.protocol + "://" + req.get("host") + req.originalUrl;
  console.log(fullUrl)
  if ((ip == "::1") & req.get("host").includes("localhost")) {
    console.log(
      "[+] ipManager functionalities restricted due to server running in local machine"
    );
    console.info(`[+] method=GET path=${fullUrl}`);
    next();
    return;
  }
  const _URL = req.originalUrl
  if (_URL.includes("documentation") || _URL.includes("weather") || _URL=="/") {
    console.log(_URL)
  } else {
    next()
    return
  }

  console.log("IP address " + ip);
  axios
    .get(`http://ip-api.com/json/${ip}`)

    // Show response data
    .then((res) => {
      const info = res.data;
      console.info(JSON.stringify(res.data));
      (async () => {
        try {
          const docRef = await addDoc(collection(db, "req_info_2022.1.22"), {
            country: info.country,
            countryCode: info.countryCode,
            region: info.region,
            regionName: info.regionName,
            city: info.city,
            zip: info.zip,
            lat: info.lat,
            lon: info.lon,
            timezone: info.timezone,
            isp: info.isp,
            org: info.org,
            as: info.as,
            ip: info.query,
            path: fullUrl,
          });
          console.log("Document written with ID: ", docRef.id);
        } catch (e) {
          console.error("Error adding document: ", e);
        }
      })()
    })
    .catch((err) => console.log(err));

  next();
};

这是控制台日志语句:
注意:请注意,console.logs 重复了两次。因此,两个文档(相同)被保存在 firebase 集合中。

Forec HTTPS 中间件

'use strict';
exports.redirectToHTTPS = (req,res,next) => {
  var schema = (req.headers['x-forwarded-proto'] || '').toLowerCase();
  if (req.headers.host.indexOf('localhost')<0 && schema!=='https') {
    res.redirect('https://' + req.headers.host + req.url);
  } else {
    next();
  }
}

【问题讨论】:

  • 啊,可怕的(async () =&gt; { })();。不要这样做。不要这样做。它会导致问题。它是一个异步函数,它返回一个 Promise,而你对这个 Promise 什么都不做。因此,难怪它与您的程序流程或错误处理中的任何其他内容完全脱节。在继续之前,无需等待该承诺完成。如果该承诺拒绝,则不会处理任何错误。
  • 我无法关注您的日志,但是这个函数是否只是被多次调用?如果是这样,每次调用console.log(fullUrl) 的输出是什么?而且,你能显示这个函数注册为中间件的代码吗?您需要添加足够多的日志记录,这样您才能了解为什么会调用它。
  • @CuriousLearner 上面的代码中没有任何内容表明此块执行两次的原因。双重执行的原因在这段代码之外,即在调用这段代码的代码中。
  • 看起来处理这个 URL http://weatherdbi.herokuapp.com/data/weather/london 的路由调用了这个函数两次。我们无法判断您的服务器是否收到了对该 URL 的两个单独的请求,或者您在服务器中此函数的上游是否有问题导致它两次调用此函数。但是,“两次”问题是您显示的代码的上游。此外,从这段代码中完全不清楚您希望如何在数据库中没有重复项,因为随着时间的推移,同一条路线被多次调用是完全正常的。
  • 将此添加为您的第一个中间件:app.use((req, res, next) =&gt;{console.log("incoming:", req.url); next();});。如果您看到同一 URL 连续记录了两次,则问题出在您的客户端,您必须显示相关的客户端代码,以便我们了解那里发生的情况。如果这只为每个 URL 记录一次,那么您的服务器代码会以某种方式为每个请求调用 ipManager 两次。

标签: javascript node.js express promise async.js


【解决方案1】:

您的代码有很多问题,但使用 async/await 代替 Promise 链和 IIFE 会更容易调试。

//imports...
exports.ipManager = async (req, res, next) => {
  const ip = req.clientIp;
  const fullUrl = `${req.protocol}://${req.get("host")}${req.originalUrl}`;
  const isLocalMachineCalling =
    (ip == "::1") && req.get("host").includes("localhost");

  if (isLocalMachineCalling) {
    console.log(
      "[+] ipManager functionalities restricted due to server running in local machine"
    );
    console.info(`[+] method=GET path=${fullUrl}`);
    next();
    return;
  }
  if (["documentation", "weather", "/"].includes(req.originalUrl)) {
    console.log(req.originalUrl);
  } else {
    next();
    return;
  }

  console.log("IP address " + ip);
  const results = await axios.get(`http://ip-api.com/json/${ip}`);
  const info = results.data;

  try {
    const docRef = await addDoc(collection(db, "req_info_2022.1.22"), {
      country: info.country,
      countryCode: info.countryCode,
      region: info.region,
      regionName: info.regionName,
      city: info.city,
      zip: info.zip,
      lat: info.lat,
      lon: info.lon,
      timezone: info.timezone,
      isp: info.isp,
      org: info.org,
      as: info.as,
      ip: info.query,
      path: fullUrl,
    });
    console.log("Document written with ID: ", docRef.id);
  } catch (e) {
    console.error("Error adding document: ", e);
  }

  next();
};

【讨论】:

  • 应用'use strict'; 是否可以改善任何事情。
  • @omenwell 我会试试你的代码。
  • .includes(req.originalUrl) 有问题,我认为 if-block 有问题。这一次,repeating issue 仅针对一条路线发生
猜你喜欢
  • 2020-11-22
  • 2018-03-24
  • 2018-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-31
  • 2021-12-01
  • 1970-01-01
相关资源
最近更新 更多