前情提要
这几天在写一个nodejs的项目,为了减少工作量便用了不少不同的AI,包括ClaudeSonnet3.5
和Gemini Exp
。于是就发现代码风格割裂严重,其中就有这个res.send
前是否加return
这个区别。
叨叨
免得废话,先说结论:强烈建议在res.send前添加return
虽然不添加时IDE也是安安静静没warning,但是还是有隐患
res.send作用
res
是给客户端的返回提示,可以使用res.send('xxx')
和res.json({...})
等方式将信息返回给客户端。但是这两者只起到了返回信息给客户端的作用,而不是终止了程序的继续运行。也就是说在这两者之后的代码会在给客户端进行返回后继续执行,如果此时当作程序终止使用,后续缺少条件判断的话容易造成语句误执行。
return作用
return
的作用就是终止当前函数,回到调用父函数。程序执行到此处时自然不会执行后续语句。各种语言都有这个,就不多说了。
举例
以下这段代码便是误执行(代码来自 devto):
const express = require('express')
const app = express()
app.use(express.json())
const port = 3000
const JSONdb = require('simple-json-db')
const db = new JSONdb('database.json')
app.post('/login', (req, res) => {
// Get the password from the POST request body
const inputPassword = req.body.password
// Check if user supplied password == the database stored password
if (inputPassword === db.get("admin")["password"]) {
res.send("\nLogin Successful!\nWelcome, Admin.\n").status(200)
} else {
res.send("\nWrong password!\nAcess denied!\n").status(401)
}
// Bug tracker counter - Will reset if code gets down to here,
// but this should never run because we used res.send()... right?!?!
db.set("bugTracker", 0);
})
app.listen(port, () => {
console.log(`Bug-Free Software Corp. App listening on port 3000!`)
console.log(`It's been ${db.get("bugTracker")} days since we've had a bug!`)
})
这段代码在输入密码之后仍然会执行db.set()
,因为res.send
并没有结束语句。也就是说每次都要去动一下数据库(此处用了json代替数据库),在大量访问之下极度消耗性能。
这个例子还只是消耗性能,要是抱着不return
也没关系的想法,后续的代码执行可能导致各种未定义的行为。导致整体崩溃或者未授权访问。
这个代码修复当然简单,直接加return:
if (inputPassword === db.get("admin")["password"]) {
// Added `return` to stop further code execution
return res.send("\nLogin Successful!\nWelcome, Admin.\n").status(200)
} else {
// Added `return` to stop further code execution
return res.send("\nWrong password!\nAcess denied!\n").status(401)
}
碎碎念
就当是留一个博客给自己长个忘记注意细节的教训吧。
参考资料:
https://dev.to/adamkatora/why-you-should-always-use-return-before-ressend-in-express-apis-and-applications-k9k dev.to的标题党程序员
https://nodejs.org/api/http.html nodejs官方对HTTP操作的详解