gpt4 book ai didi

javascript - 为什么有时异步代码中的错误会使 node.js 服务器崩溃

转载 作者:行者123 更新时间:2023-11-30 06:16:50 25 4
gpt4 key购买 nike

我在某些网站上读到,express.js 中“异步代码中任何 Uncaught Error 都可能导致 HTTP 服务器崩溃,从而导致 DoS”。我做了这个例子来检查它,但我想知道为什么如果错误发生在快速回调中,服务器不会崩溃,但如果它发生在 setTimeout() 函数中,服务器会崩溃。

错误不是发生在两个示例的异步代码中,还是其中一个不是异步代码而我弄错了?为什么某些异步代码中的未捕获错误会导致服务器崩溃,而其他异步代码中却不会?

var express = require("express");

var app = express();

http: app.get("/e1", (req, res, next) => {
let p = req.query.p;
let pn = parseInt(p, 10);

//If the error happens here the server does not crashes
let s = pn + y; // y does not exist, so an error occurs

res.send("hi");
});

http: app.get("/e2", (req, res, next) => {
let p = req.query.p;
let pn = parseInt(p, 10);

setTimeout(() => {
//If the error happens here the server crashes
let s = pn + y; // y does not exist, so an error occurs
}, 100);

res.send("hi");
});

app.listen(3000, function() {
console.log("Example app listening on port 3000!");
});

最佳答案

如果我们想到throwcatch堆栈 上操作,可能会变得清楚:

throw:在堆栈中向下移动,直到找到处理程序,然后从那里继续。

catch 将错误处理程序添加到堆栈。

对于同步代码,可以将其可视化为:

 // Legend:
-> function call
<- function returns

http.request -> express.handler -> [try] -> your function -> nested call -> Throw!
<- <- [catch] <-----------------------------------

现在,当您开始一个异步操作时,回调将在某个时候被回调,并且该回调将在一个新的堆栈上结束:

 // the current stack:
http.request -> express.handler -> [try] -> your function -> start async action
<- <- <- <- <-

// somewhen later, the timeout calls back
timer -> your setTimeout callback -> nested call -> Throw!
Crash! <-----------------------------------------------------

现在 Express 将一个 catch 处理程序附加到您代码中的回调:

 Express.get = function(callback) {
//...
try {
callback(req, res, next);
} catch(error) {
// handle error
}
};

这将处理错误,但只是同步错误(经过简化,实际代码是 here )


现在应该怎么做才能处理这个问题?

基本上:将每个回调包装到一个 promise 中(因为这使得异步错误处理更容易):

 const delay = ms => new Promise(res => setTimeout(res, ms));

然后 await 您创建的每个 promise ,并将所有这些包装在 try/catch 中:

 app.get(async (req, res) => {
try {
await delay(2000);
const p = q + d;
} catch(error) {
res.status(500).send("whoops");
}
});

之所以可行,是因为 await“保持堆栈”(但只是 async 函数之一在嵌套调用上 await,这就是为什么我们需要添加我们自己的 try/catch 因为 Express 不会在回调调用上 await),因此嵌套 await ed 函数将回退到我们的错误处理程序。

 http.request -> express.handler -> [async] -> [try] -> nested call -> [await]
<- <- <-
// synchronous code returned, the [async] stack will be kept
[async] -> [try] -> nested call -> [await]

// somewhen, the promise resolves, execution coninues:
[async] -> [try] -> nested call -> Throw!
<- <- [catch] <--------------

关于javascript - 为什么有时异步代码中的错误会使 node.js 服务器崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55617958/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com