javascript - 关于嵌套 try catch 语句和错误处理的问题
问题描述
由于不同的包装器和管道中相互传递的东西,我正在处理多个嵌套的 try catch 语句。
我试图通过模拟响应并在数据最终传递到某个地方调用 .json() 并抛出如下定义的错误时抛出一个名为 put 的函数的 catch 块的测试覆盖率:
it('hits the catch', async () => {
fetch.mockImplementation(() =>
Promise.resolve({
ok: true,
json: () => {
throw { type: 'error', message: 'hit the catch' }
},
})
)
expect(
await put({
path: '/script/1',
body: {
name: 'newName',
},
})
).toThrow({
message: 'hit the catch',
type: 'error',
})
})
该函数依次调用客户端函数:
export const put = async <I, R>({ path, body }: { path: string; body: I }) => {
try {
return client<I>(getServiceUrl(path), 'PUT', getServiceHeaders(token), body)
} catch (e) {
throw handleClientError(e)
// return handleClientError(e)
}
}
客户端函数是 fetch 的包装器:
export const client = async <I>(
url: string,
method: 'POST' | 'GET' | 'PUT' | 'PATCH' | 'DELETE',
headers: HeadersInit,
body?: I
): Promise<ServiceResonse<I>> => {
try {
const res: Response = await fetch(url, {
method,
headers,
body: JSON.stringify(body),
})
return getServiceResponse(res)
} catch (e) {
throw handleClientError(e)
// return handleClientError(e)
}
}
这里也调用了各种辅助函数:
export const getServiceHeaders = (token: string = ''): HeadersInit => {
try {
if (token) {
return {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + token,
}
} else {
return {
'Content-Type': 'application/json',
}
}
} catch (e) {
const msg = 'Error getting service headers ' + JSON.stringify(e)
console.error(msg) //shouldn't ever happen
throw new Error(msg)
}
}
export const getServiceResponse = async <T>(
response: Response
): Promise<ServiceResonse<T>> => {
try {
const data = await response.json()
if (!response.ok) {
let error = {
code: (data && data.code) || 'error',
message:
(data && data.message) ||
response.statusText ||
'Unkown Error x03391aa00',
invalid: null,
}
switch (response.status) {
case 400:
if (error.code == 'invalid') {
return (error.invalid = ((data && data.errors) || []).reduce(
(items: RequestErrorResponseFields, i: APIResponseErrorItem) => {
items[i.field] = i.message
return items
},
{}
))
}
break
case 401:
// TODO handle error)
return { type: 'error', fields: {}, message: 'Invalid Token' }
break
}
return Promise.reject(error)
} else {
return data
}
} catch (e) {
throw e
}
}
export const getServiceUrl = (
path: string,
options: { [k: string]: string | number } = {}
): string => {
if (typeof path !== 'string') throw new Error('path must be of type string')
if (typeof options !== 'object')
throw new Error('options must be of type object')
const query = Object.keys(options)
.map(k => k + '=' + options[k])
.join('&')
//todo move to general configuration file, still use process.env
const baseUrl = process.env.API_URL || 'http://localhost/ipa'
return `${baseUrl}${path}${query.length ? '?' + query : ''}`
}
export const handleClientError = (
err: { message?: string } | RequestErrorResponse
) => {
if ('type' in err) {
throw err
// return Promise.reject(err)
} else {
throw {
code: 'error',
message: err.message || 'Unkown - 0x39aef3991',
errors: [],
}
// return Promise.reject({
// code: 'error',
// message: err.message || 'Unkown - 0x39aef3991',
// errors: [],
// })
}
}
我试图通过强制异常并将其传递给 catch 来测试 put 函数中的 catch 块的覆盖率,但我似乎无法达到它。我不确定在什么时候强制和异常,然后如何传递它并对其进行测试。有没有人对我应该如何处理这个或我缺少什么有任何想法?
解决方案
在你的async put
函数中,你有一行返回一个 Promise:
返回客户端(getServiceUrl(路径),'PUT',getServiceHeaders(令牌),正文)
这条线周围的 try/catch 块将捕获同步抛出的错误,但不会捕获异步错误。如果要使用try/catch
块来捕获这些异步错误,则需要添加一条await
语句:
export const put = async <I, R>({ path, body }: { path: string; body: I }) => {
try {
return await client<I>(getServiceUrl(path), 'PUT', getServiceHeaders(token), body)
} catch (e) {
throw handleClientError(e)
// return handleClientError(e)
}
}
或者,您可以使用常规的承诺捕获:
return await client<I>(getServiceUrl(path), 'PUT', getServiceHeaders(token), body).catch(handleClientError)
(注意:我没有完全浏览代码——那里可能有更多的异步问题)
推荐阅读
- schema - 自定义架构上的 Google CEL 查询(动态组)
- amazon-s3 - 使用服务器端加密上传和获取 S3 存储桶的文件 URL
- python - 如何在pydot中制作独立边
- java - 点击“删除”后删除通知
- reactjs - Bulma Hamberger 扩展右侧而不是底部
- python - 使用 Google Colab 将文件从数组移动到 Google Drive 中的一个目录到另一个目录
- docker - 连接卷时数据源的优先级
- javascript - 从 Typescript 中的配置文件返回 Promise
- python-3.x - 为什么 CSV 文件在 pwd 中时找不到且无法读取?
- database - 如何将位置(城市、国家等)从一个数据库映射到另一个数据库