内部函数或调用函数是否应该包含在 try-catch 块中以进行正确的错误处理?
Should the inner function or the calling function be wrapped within a try-catch block for correct error handling?
是否应该将内部函数或调用函数包装在 try-catch 块中以进行正确的错误处理?
示例 1
// Async function definition
const getLatestRecords = async() => {
try {
const records = await Record.find({})
return records
} catch(e) {
console.error(e)
}
}
// Async function call without error handling - will this suffice?
let records
const callAsyncFunction = async() => {
records = await getLatestRecords()
}
callAsyncFunction()
// Same async function call with error handling - or should it be like this?
let records
const callAsyncFunctionWithTryCatch = async() => {
try {
records = await getLatestRecords()
} catch(e) {
console.error(e)
}
}
callAsyncFunctionWithTryCatch()
Q1) 在上面的示例中,异步函数定义 getLatestRecords() 已经包含在 try-catch 块中以防出错处理。尽管如此,由 callAsyncFunction() 定义的调用函数是否足够,或者异步函数调用是否也应该包装在 try-catch 块中,如 callAsyncFunctionWithTryCatch 所示()?
示例 2
// Test without try catch block - will this suffice?
test('Should delete records with valid id', async() => {
const record = await new Record().save()
const res = await request(app)
.delete(`/records/${record._id}`)
.expect(200)
expect(await Records.countDocuments()).toBe(0)
})
// Test with try catch block - should all tests with await in them be wrapped in a try catch block?
test('Should delete records with valid id', async() => {
try {
const record = await new Record().save()
const res = await request(app)
.delete(`/records/${record._id}`)
.expect(200)
expect(await Records.countDocuments()).toBe(0)
} catch(e) {
console.error(e)
}
})
Q2) 同样,对于测试,是否应该将所有带有 await 调用的测试包装在 try catch 块中?请记住,有人希望测试在出现问题时失败,所以我对此不太确定。
如果您知道可以在该函数中处理与错误有关的所有事情,则只应将它们包含在try/catch
中。否则,您应该让函数的 consumer 决定如何处理错误。例如,对于 getLatestRecords
,如果在使用它的脚本周围有各种不同的点,那么让 这些不同的点 处理错误可能是最有意义的,具体取决于他们的背景。例如:
const getLatestRecords = async () => {
const records = await Record.find({})
return records
}
// could also just do: `return Record.find({})`
getLatestRecords()
.then(doStuff)
.catch((err) => {
res.status(500).send('Could not retrieve records for ' + user);
});
如果将 try
/catch
放在内部 getLatestRecords
函数中,另一方面,消费者将不得不通过检查 return 值存在,而不是 .catch
,这有点奇怪。
如果所有 await
都在 try/catch
内,包含 async
的函数将永远不会拒绝。因此,让 async
函数的调用者将它放在 try/catch
中不会完成任何事情,因为内部函数永远不会拒绝; catch
永远不会被输入。也就是说,对于这个例子:
const getLatestRecords = async() => {
try {
const records = await Record.find({})
return records
} catch(e) {
console.error(e)
}
}
const callAsyncFunctionWithTryCatch = async() => {
try {
records = await getLatestRecords()
} catch(e) {
console.error(e)
}
}
callAsyncFunctionWithTryCatch()
多此一举;简化为
const getLatestRecords = async() => {
try {
const records = await Record.find({})
return records
} catch(e) {
console.error(e)
}
}
const callAsyncFunctionWithTryCatch = async() => {
records = await getLatestRecords()
}
callAsyncFunctionWithTryCatch()
(或仅在 callAsyncFunctionWithTryCatch
中捕获 - 但不要在 两者中捕获 )
- should the async function call also be wrapped in a try-catch block
如果一个 async
函数被包装在 try/catch 中,你不需要在多个层次上使用它,除非有一些代码可能会抛出错误并且没有被 try/catch 包装=].例如:
const getLatestRecords = async() => {
aFunctionWhichCanThrow(); // <= Only need try/catch in caller fn for this
try {
const records = await Record.find({})
return records
} catch(e) {
console.error(e)
}
}
即使在那种情况下,您也可能希望通过全局 unhandledRejection
处理程序来处理错误。
- should all tests with await calls in them be wrapped in a try catch block
是的,可以 throw/reject 的测试应该包含在 try/catch 块中。这些案例可能是这样的:
- 函数应该不抛出
- try - 验证函数响应
- 赶上 - 测试失败
- 函数应该抛出
- 尝试 - 测试失败
- catch - 验证错误
是否应该将内部函数或调用函数包装在 try-catch 块中以进行正确的错误处理?
示例 1
// Async function definition
const getLatestRecords = async() => {
try {
const records = await Record.find({})
return records
} catch(e) {
console.error(e)
}
}
// Async function call without error handling - will this suffice?
let records
const callAsyncFunction = async() => {
records = await getLatestRecords()
}
callAsyncFunction()
// Same async function call with error handling - or should it be like this?
let records
const callAsyncFunctionWithTryCatch = async() => {
try {
records = await getLatestRecords()
} catch(e) {
console.error(e)
}
}
callAsyncFunctionWithTryCatch()
Q1) 在上面的示例中,异步函数定义 getLatestRecords() 已经包含在 try-catch 块中以防出错处理。尽管如此,由 callAsyncFunction() 定义的调用函数是否足够,或者异步函数调用是否也应该包装在 try-catch 块中,如 callAsyncFunctionWithTryCatch 所示()?
示例 2
// Test without try catch block - will this suffice?
test('Should delete records with valid id', async() => {
const record = await new Record().save()
const res = await request(app)
.delete(`/records/${record._id}`)
.expect(200)
expect(await Records.countDocuments()).toBe(0)
})
// Test with try catch block - should all tests with await in them be wrapped in a try catch block?
test('Should delete records with valid id', async() => {
try {
const record = await new Record().save()
const res = await request(app)
.delete(`/records/${record._id}`)
.expect(200)
expect(await Records.countDocuments()).toBe(0)
} catch(e) {
console.error(e)
}
})
Q2) 同样,对于测试,是否应该将所有带有 await 调用的测试包装在 try catch 块中?请记住,有人希望测试在出现问题时失败,所以我对此不太确定。
如果您知道可以在该函数中处理与错误有关的所有事情,则只应将它们包含在try/catch
中。否则,您应该让函数的 consumer 决定如何处理错误。例如,对于 getLatestRecords
,如果在使用它的脚本周围有各种不同的点,那么让 这些不同的点 处理错误可能是最有意义的,具体取决于他们的背景。例如:
const getLatestRecords = async () => {
const records = await Record.find({})
return records
}
// could also just do: `return Record.find({})`
getLatestRecords()
.then(doStuff)
.catch((err) => {
res.status(500).send('Could not retrieve records for ' + user);
});
如果将 try
/catch
放在内部 getLatestRecords
函数中,另一方面,消费者将不得不通过检查 return 值存在,而不是 .catch
,这有点奇怪。
如果所有 await
都在 try/catch
内,包含 async
的函数将永远不会拒绝。因此,让 async
函数的调用者将它放在 try/catch
中不会完成任何事情,因为内部函数永远不会拒绝; catch
永远不会被输入。也就是说,对于这个例子:
const getLatestRecords = async() => {
try {
const records = await Record.find({})
return records
} catch(e) {
console.error(e)
}
}
const callAsyncFunctionWithTryCatch = async() => {
try {
records = await getLatestRecords()
} catch(e) {
console.error(e)
}
}
callAsyncFunctionWithTryCatch()
多此一举;简化为
const getLatestRecords = async() => {
try {
const records = await Record.find({})
return records
} catch(e) {
console.error(e)
}
}
const callAsyncFunctionWithTryCatch = async() => {
records = await getLatestRecords()
}
callAsyncFunctionWithTryCatch()
(或仅在 callAsyncFunctionWithTryCatch
中捕获 - 但不要在 两者中捕获 )
- should the async function call also be wrapped in a try-catch block
如果一个 async
函数被包装在 try/catch 中,你不需要在多个层次上使用它,除非有一些代码可能会抛出错误并且没有被 try/catch 包装=].例如:
const getLatestRecords = async() => {
aFunctionWhichCanThrow(); // <= Only need try/catch in caller fn for this
try {
const records = await Record.find({})
return records
} catch(e) {
console.error(e)
}
}
即使在那种情况下,您也可能希望通过全局 unhandledRejection
处理程序来处理错误。
- should all tests with await calls in them be wrapped in a try catch block
是的,可以 throw/reject 的测试应该包含在 try/catch 块中。这些案例可能是这样的:
- 函数应该不抛出
- try - 验证函数响应
- 赶上 - 测试失败
- 函数应该抛出
- 尝试 - 测试失败
- catch - 验证错误