【问题标题】:Node Express app freezes unless page is loaded from a new browser tab除非从新的浏览器选项卡加载页面,否则 Node Express 应用程序会冻结
【发布时间】:2019-12-12 09:01:24
【问题描述】:

我的 Node JS Web 应用程序有一些非常不稳定的行为。对于某些路线,页面将加载一次 - 但任何尝试单击应用程序中其他位置的链接或页面刷新都将不起作用。浏览器会变白,加载器永远旋转。有些页面更不稳定 - 它们可以正常工作,但可能在第 15 个页面加载时,同样的问题会出现。

服务器控制台或浏览器中没有错误。我已经使用 Visual Studio 调试器逐步完成了该应用程序,它正在查找路线、访问数据库并从服务器的角度来看,每次都完成请求而不会出错。在浏览器中,当它崩溃时,它会出现在控制台中,它似乎正在接收一点点标记 - 只是 <html><title>....</title><body></body></html>,但没有别的。

发生这种情况时,重新启动 Node 服务器无效。唯一的解决方案是打开一个新的浏览器选项卡,然后再次发出请求——这在 100% 的时间内都有效。谁能解释这种行为,以及如何诊断问题?

应用程序在本地托管,使用 mysql、express、express-myconnection 和 ejs 库。应用的基本结构是这样的:

app.use(myConnection(mysql, dbOptions, "pool"));
app.set("view engine", "ejs");
var scraper = require("./routes/scraper");
var cookieParser = require("cookie-parser");
var session = require("express-session");
app.use(cookieParser("keyboard cat"));
app.use(
   session({
      secret: "keyboard cat",
      resave: false,
      saveUninitialized: true,
      cookie: { maxAge: 60000 }
   })
);

app.get("/siteReview/(:id)", function(req, res, next) {
   const sourceId = req.params.id;
   req.getConnection(function(error, conn) {
      conn.query(`select website_data from orgs where id = ` + sourceId, function(err, rows) {
         if (err) throw err;
         res.render("siteReview", {
            title: "Site review",
            orgId: sourceId,
            websiteData: JSON.parse(rows[0].website_data)
         }); 
      });
   });
});

【问题讨论】:

  • 我建议您打开 Chrome 开发者工具并查看网络选项卡。然后,查找从浏览器到您的服务器的某种未完成且仍处于打开状态、等待完成的请求。
  • 仅供参考,您展示的一个请求处理程序根本没有错误处理。因此,如果req.getConnection()con.query() 出现错误,则不会向浏览器发送任何内容,并且该请求处理程序就坐在那里,最终超时。您应该处理服务器上的所有错误,并在您的服务器出现错误时发送某种错误状态(可能是 5xx)。 if (err) throw err 永远不应该像您一样在普通的异步回调中使用,因为没有人可以捕获并适当地处理它,并且由于它是异步的,因此无法在更高级别上捕获它。

标签: node.js express ejs


【解决方案1】:

首先向您显示的一个请求处理程序添加一些错误处理,以便如果有任何错误,则仍会处理请求并发送错误状态,并且您会在服务器上获得适当的日志记录:

app.get("/siteReview/(:id)", function(req, res) {
   const sourceId = req.params.id;
   req.getConnection(function(error, conn) {
      if (error) {
          console.log("error on req.getConnection()", error);
          res.sendStatus(500);
          return;
      }
      conn.query(`select website_data from orgs where id = ` + sourceId, function(err, rows) {
         if (err) {
             console.log("error on conn.query()", err);
             res.sendStatus(500);
             return;
         }
         res.render("siteReview", {
            title: "Site review",
            orgId: sourceId,
            websiteData: JSON.parse(rows[0].website_data)
         }); 
      });
   });
});

我不知道这是否会导致您看到的确切问题,但这是修复并确保没有来自浏览器的请求被放弃并最终超时的良好第一步。


然后,如果问题仍然存在,我建议您打开 Chrome 开发人员工具并查看网络选项卡。然后,查找从浏览器到您的服务器的某种请求,该请求未完成且仍处于打开状态,等待完成。它可能不是主页的 URL,但可能是页面在初始化自身和加载其所有资源的过程中正在执行的其他资源或 Ajax 调用。


而且,你永远不应该写这行代码:

if (err) throw err;

在一个普通的异步回调中。所做的只是将异常抛出回回调来自的任何异步系统的内部,您的代码中没有任何一个可以处理它。对 node.js 文档感到羞耻,因为在他们的编码示例中显示了这一点。编写这种类型的错误处理永远不是正确的方法。如果你要扔,你必须扔到能接住它的东西上。像这两种情况一样的普通异步回调并没有为您的代码提供捕获该异常的方法,因此它没有得到处理,这对服务器总是不利的。

【讨论】:

  • 这很有帮助,我会更好地处理错误(我盲目地遵循样板示例)。在这种情况下,在服务器端没有发现错误。一切都在加载 - 但是我注意到页面加载正在 jQuery 库中的断点处停止,并且按下“继续执行”会导致正确的页面加载。因此,对无尽的白屏进行了解释。奇怪的是,我从来没有设置断点,也没有关闭它。其他人报告了这种行为,显然这是一个 chrome 错误,恢复默认用户设置可以解决。
  • @Rusty - 您是否正在使用某种自定义版本的 jQuery 调试?您可以清除 Chrome 调试器中的所有断点。
  • 不——只是普通的 jQuery。但是恢复默认设置的问题已经解决了。
猜你喜欢
  • 2019-08-16
  • 2020-12-28
  • 1970-01-01
  • 2017-02-16
  • 2017-01-06
  • 2021-03-10
  • 1970-01-01
  • 1970-01-01
  • 2021-10-28
相关资源
最近更新 更多