当我在下面的函数中输入catch
块时,我的问题是(似乎(事情超出了范围,或者范围被污染了:
export const getOne = model => async (req, res, next) => {
let id = req.params.id
let userId = req.user
try {
let item = await model.findOne({ _id: id, createdBy: userId }).exec()
if (!item) {
throw new Error('Item not found!')
} else {
res.status(200).json({ data: item }) // works perfectly
}
} catch (e) {
res.status(400).json({ error: e }) // TypeError: res.status(...).json is not a function
// also TypeError: next is not a function
// next(e)
}
}
有趣的是,在catch
块中使用res.status(...).end()
工作得很好,但我无法将任何细节与响应一起发送回来,这让我很困扰。根据res.send()
和res.json
的Express Documentation,我应该能够连锁.status()
,同样有趣的是,如果事情成功的话,它在上面的try
语句中运行得很好——res.status(200).json(...)
运行得很完美。
此外,正如Express文档中所建议的,我尝试将错误处理抽象到中间件,通过闭包,我应该仍然可以访问catch
语句中的next
,对吧?为什么这不是一个函数?
- 为什么
res.status(...).json(...)
在我的try
块中工作,而在catch
块中不工作 - 为什么
next
不再是catch
块中的函数
提前感谢!
编辑
这在单元测试中失败了,下面的代码产生了上面描述的错误:
describe('getOne', async () => {
// this test passes
test('finds by authenticated user and id', async () => {
expect.assertions(2)
const user = mongoose.Types.ObjectId()
const list = await List.create({ name: 'list', createdBy: user })
const req = {
params: {
id: list._id
},
user: {
_id: user
}
}
const res = {
status(status) {
expect(status).toBe(200)
return this
},
json(result) {
expect(result.data._id.toString()).toBe(list._id.toString())
}
}
await getOne(List)(req, res)
})
// this test fails
test('400 if no doc was found', async () => {
expect.assertions(2)
const user = mongoose.Types.ObjectId()
const req = {
params: {
id: mongoose.Types.ObjectId()
},
user: {
_id: user
}
}
const res = {
status(status) {
expect(status).toBe(400)
return this
},
end() {
expect(true).toBe(true)
}
}
await getOne(List)(req, res)
})
})
为什么res.status(…(.json(…(在我的try块中有效,但在catch块中无效?
似乎您正在传递一个只有status
&end
方法在运行时使用单元测试。这就是为什么它找不到json
方法