提问人:Siddharth Potti 提问时间:8/5/2022 最后编辑:LayhoutSiddharth Potti 更新时间:8/6/2022 访问量:184
为什么当参数较少时回调函数会起作用?
Why does callback function work when there are fewer arguments?
问:
有人可以解释为什么在函数 verifyUser 中,函数 verifyToken 被传递回调函数作为第四个参数时,此代码有效。但是如果我们看一下 verifyToken 函数,它只有 3 个参数/参数。这是如何工作的????
import jwt from "jsonwebtoken";
import { createError } from "../utils/error.js";
export const verifyToken = (req, res, next) => {
const token = req.cookies.access_token;
if (!token) {
return next(createError(401, "You are not authenticated!"));
}
//Verifying if token is correct
//Error (err) or token data (user) are returned by verify function
jwt.verify(token, process.env.JWT, (err, user) => {
if (err) return next(createError(403, "Token is not valid!"));
req.user = user;
next();
});
};
export const verifyUser = (req, res, next) => {
verifyToken(req, res, next, () => {
if (req.user.id === req.params.id || req.user.isAdmin) {
next();
} else {
return next(createError(403, "You are not authorized!"));
}
});
};
答:
0赞
Brother58697
8/5/2022
#1
我去挖掘Express的源代码,找到了这个文档
调用函数后,就像中间件一样 它将继续执行路由或后续参数函数。
next()
因此,看起来首先尝试调用回调参数(如果它已传递),然后尝试调用下一个中间件。next()
我认为他们这样做的原因,是在不改变他们的实现的情况下硬编码或链接对之前的调用,这些实现在调用时会跳转到下一个中间件而不是继续。verifyToken
verifyUser
next()
verifyToken
verifyUser
我写了一个示例脚本,在这里使用了相同的想法:
function printResult(object, next) {
console.log("The final results is: " + object.result);
next();
}
function printLog(object, next){
console.log('Running printLog')
console.log('The current result is: ' + object.result)
next();
}
function add5(object, next) {
// Chain printLog before add5 so that it always runs before it
printLog(object, next, () => {
console.log('Now running add5')
object.result = object.result + 5;
next();
})
}
function addOne(object, next) {
console.log('Running addOne')
object.result = object.result + 1;
next();
}
function callStack(stack, object) {
function next(index, object) {
return function runNext() {
let caller = runNext.caller
if(caller.name !== '' && caller.arguments[2]) {
caller.arguments[2]()
} else if (stack[index + 1]){
stack[index + 1](object, next(index + 1, object));
}
}
}
stack[0](object, next(0, object));
}
const stack = [addOne, add5, printResult]
const object = {result: 0}
callStack(stack, object)
请注意,存在匿名函数检查,因为检查匿名函数的 arguments 属性会引发错误。caller.name !== ''
更全面地解释为什么这很重要。
因此,如果您的应用程序是这样的,则没有问题:
- 中间件 1
next()
转到下一个中间件
- verifyToken(中间件 2)
next()
转到下一个中间件
- 中间件 3
但是如果是这样的,没有调用参数函数:next()
- 中间件 1
next()
转到下一个中间件
verifyUser
(中间件 2)- 调用
verifyToken
next()
in 转到下一个中间件 <- 这是一个问题verifyToken
- 继续< - 因为这永远不会发生
verifyUser
next()
转到下一个中间件
- 调用
- 中间件 3
因此,他们让调用一个参数函数:next()
- 中间件 1
next()
转到下一个中间件
verifyUser
(中间件 2)- 使用 的实现作为回调进行调用(例如,使用别名)
verifyToken
verifyUser
veryifyCB
next()
in 检查回调,查找并调用它verifyToken
verifyCB
next()
在转到下一个中间件verifyCB
- 使用 的实现作为回调进行调用(例如,使用别名)
- 中间件 3
评论
0赞
Siddharth Potti
8/6/2022
是的!这正是我想要的!
上一个:如何返回异步调用的响应?
评论
verifyUser()
verifyToken()
verifyToken()
verifyToken()
verifyToken()
next()
if (req.user.id === req.params.id || req.user.isAdmin)
console.log("in my callback passed to verifyToken()");