Javascript 为什么异步代码中的错误有时会导致node.js服务器崩溃
我在一些网站上读到,在express.js中,“异步代码中的任何未捕获错误都可能导致HTTP服务器崩溃,从而导致DoS”。 我制作了这个示例来检查它,但是我想知道为什么如果错误发生在express回调中,服务器不会崩溃,但是如果它发生在setTimeout()函数中,服务器会崩溃 这两个例子中的错误不是都发生在异步代码中,还是其中一个不是异步的,我错了? 为什么某些异步代码中的未捕获错误会导致服务器崩溃,而其他异步代码中的错误不会导致服务器崩溃Javascript 为什么异步代码中的错误有时会导致node.js服务器崩溃,javascript,node.js,asynchronous,error-handling,crash,Javascript,Node.js,Asynchronous,Error Handling,Crash,我在一些网站上读到,在express.js中,“异步代码中的任何未捕获错误都可能导致HTTP服务器崩溃,从而导致DoS”。 我制作了这个示例来检查它,但是我想知道为什么如果错误发生在express回调中,服务器不会崩溃,但是如果它发生在setTimeout()函数中,服务器会崩溃 这两个例子中的错误不是都发生在异步代码中,还是其中一个不是异步的,我错了? 为什么某些异步代码中的未捕获错误会导致服务器崩溃,而其他异步代码中的错误不会导致服务器崩溃 var express = require("ex
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!");
});
如果我们想到在堆栈上运行的
throw
和catch
,则可能会变得很清楚:
throw
:沿着堆栈向下移动,直到找到处理程序,然后从那里继续
catch
将错误处理程序添加到堆栈中
对于同步代码,可以将其可视化为:
// Legend:
-> function call
<- function returns
http.request -> express.handler -> [try] -> your function -> nested call -> Throw!
<- <- [catch] <-----------------------------------
这将处理错误,但只是同步错误(简化了,实际代码是)
现在我们该怎么处理呢 基本上:将每个回调包装成一个承诺(这样可以更轻松地处理异步错误): 然后,等待你做出的每一个承诺,并将所有承诺包装在一个“尝试”/
捕获”
:
app.get(async (req, res) => {
try {
await delay(2000);
const p = q + d;
} catch(error) {
res.status(500).send("whoops");
}
});
这是因为await
“保留堆栈”(但仅是异步
函数中的一个函数在嵌套调用上等待,这就是为什么我们需要添加自己的try
/catch
,因为Express在回调调用上不等待),因此,一个嵌套的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] <--------------
http.request->express.handler->[async]->[try]->嵌套调用->[wait]
[等待]
//有时,承诺解决了,执行就结束了:
[async]->[try]->嵌套调用->抛出!
验证输入并使用try/catchExpress是否默认处理错误?那么,您是说express路由处理函数回调是同步代码?那么,为什么它在express文档中被称为回调?@v8rs不,我不是这么说。我不明白express route处理程序是如何捕捉到回调的error@v8rs由于回调call周围有一个try{}catch(e){}
块,我仍然不理解它,我没有在快速回调中使用try-catch块,但express回调中发生的错误不会使应用程序崩溃
const delay = ms => new Promise(res => setTimeout(res, ms));
app.get(async (req, res) => {
try {
await delay(2000);
const p = q + d;
} catch(error) {
res.status(500).send("whoops");
}
});
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] <--------------