我正在尝试使用纯功能路由控制器功能,并且我有一个快速路由控制器:
router.get('/', serveJson((x, y) => (x > 5 ? {
x: x + y
} : WHAT)))
serveBody
是一个中间件,它为处理函数提供参数x
和y
,并执行常规的res.json(...)
。
要使控制器抛出错误,应该用什么代替WHAT
?还是有其他方法在功能代码中引发错误?
我尝试了throw "x should be smaller than 5"
,但这行不通,而且没有正确执行。
答案 0 :(得分:1)
还是有其他方法在功能代码中引发错误?
丢球错误是一个副作用,因此完全不起作用。但是,express会利用它们使服务器以某些方式做出响应,因此这有点超出您的控制范围。您将必须在某个时候throw
...
我同意“技巧”是编写动态路由处理程序,但我想我会从@eol编写他们的方式中对其进行一些更改
x > 5
代码是路径中lambda的一部分,但是错误消息x should be greater than 5
是不可配置的。如果lambda更改为x > 6
,则错误消息将毫无意义
单分支if
语句很奇怪,并且对未使用的分支要求undefined
是代码中的缺陷。也许将Error
移到这个位置?
这是经过修改的处理程序的外观-
const serveJson = (cb) => (req, res, next) => {
const x = Number(req.query.x)
const y = Number(req.query.y)
const data = cb(x, y)
if (data instanceof Error)
throw data
else
res.json(data)
}
app.get('/test', serveJson((x, y) =>
x > 5
? { x: x + y }
: Error(`value for x (${x}) cannot exceed 5`)
))
仍然存在问题。 serveJson
不适合通用,因为它总是查询x
和y
参数,这使我们质疑为什么它是一个单独的函数。您需要定义几条路由来专门读取x
和y
请求参数?
您会这样使用吗?我不知道,感觉像是触手可及-
app.get('/add', serveJson((x, y) =>
x > 5
? { result: x + y }
: Error(`value for x (${x}) cannot exceed 5`)
))
app.get('/mult', serveJson((x, y) =>
x > 10
? { result: x * y }
: Error(`value for x (${x}) cannot exceed 10`)
))
app.get('/divide', serveJson((x, y) =>
x !== 0
? { result: x / y }
: Error(`divisor cannot be zero`)
))
您是否真的会有很多可以像这样使用serveJson
的地方?这似乎不太可能,但是为了击败一匹死马,让我们通过指定我们要使用的参数来尝试使serveJson
更加灵活。会解决的,对吧?
const serveJson = (params, cb) => (req, res, next) => {
const data = cb(...params.map(p => Number(req.query[p])))
if (data instanceof Error)
throw data
else
res.json(data)
}
app.get('/test', serveJson(['x', 'y'], (x, y) =>
x > 5
? { result: x + y }
: Error(`value for x (${x}) cannot exceed 5`)
))
这将被视为功能更强大,因为所有相互关联的部分都是serveJson
调用站点上的可配置参数。但是您仍然有一个巨大的问题-假设所有参数都是数字,并尝试相应地解析/验证它们。
当然,您可以继续努力并提出一些建议-
app.get('/test/, serveJson({ x: Number, y: Number, z: String }, (x, y, z) =>
// ...
))
但是请注意,所有外部规范都变得越来越大。好像完全跳过serveJson
会更容易。没有隐藏的意图,具有100%的灵活性-
app.get('/test', (req, res, next) => {
const x = Number (req.params.x)
const y = Number (req.params.y)
if (x > 5)
res.json({ result: x + y })
else
throw Error(`value for x (${x}) cannot exceed 5`)
})
在所有这些操作的最后,您要求提供一个根本不存在的魔术子弹。至少在您开始想象不平凡的情况时,与您的操作手册中提供的伪代码不同,至少没有。
请在整个程序中共享更多上下文。我认为每个人都可以更有效地为您提供帮助。
答案 1 :(得分:0)
您可以做的是返回例如null
或undefined
,并在serveJson
中间件中处理此结果。像这样:
const serveJson = (cb) => {
return function (req, res, next) {
// TODO: Validate input
const x = Number.parseInt(req.query.x);
const y = Number.parseInt(req.query.y);
const result = cb(x, y);
if (typeof res === 'undefined') {
throw new Error("x should be greater than 5");
}
res.json({ result });
}
};
app.get('/test', serveJson((x, y) => (x > 5 ? { x: x + y } : undefined)));
如果您现在致电/test?x=6&y=3
,您会得到
{"result":{"x":9}}
如果您致电/test?x=3&y=3
,则会收到错误消息:
Error: x should be greater than 5
答案 2 :(得分:0)
我最终要做的是依靠路由处理程序和serveJson
包装程序之间的合同。我返回这样的对象:
{
body: "X should be greater than 5",
status: 400
}
serveJson
正在检查status
字段,如果它是400,它将抛出一个异常,供快速中间件处理。
路由处理程序如下:
app.get('/test', serveJson((x, y) => (x > 5 ? { body: "1234", status: 200 } : {
body: "X should be greater than 5",
status: 400
})));
还有serveJson
:
const serveJson = (cb) => {
return function (req, res, next) {
const result = cb({req.query);
if (result.status === 400) {
throw new Error(result.body);
}
res.json({ result });
}
};
通过这种方式,路由处理程序是一个获取参数的纯函数,并且在输入错误的情况下,它通过与status: 400
的约定来响应。