在 TypeScript 中使用 Promises 的异步函数的正确错误模式
Posted
技术标签:
【中文标题】在 TypeScript 中使用 Promises 的异步函数的正确错误模式【英文标题】:Proper error pattern for async functions using Promises in TypeScript 【发布时间】:2017-06-11 07:43:08 【问题描述】:我想创建一个具有正确错误处理的类型化异步函数。
我可以这样定义:
export async function doSomething(userId:string) : Promise<ISomething | void>
let somthing: ISomething = ;
try
something.user = await UserDocument.findById(userId);
something.pet = await PetDocument.findOne(ownerId:userId);
return Promise.resolve(something);
catch (err)
console.log("I would do some stuff here but I also want to have the caller get the error.");
return Promise.reject(err);
...这似乎可行,但是(原因很清楚),如果我尝试将结果分配给ISomething
对象,我会收到错误Type 'void | ISomething' is not assignable to type 'ISomething'
。
let iSomething:ISomething;
iSomething = await doSomething('12'); //this give me the error
我明白这是为什么。我的问题是,在这种情况下,我应该使用什么模式进行错误处理?请注意,如果返回类型是 Promise<IProfile>
,那么我会收到 return Promise.reject(err);
行的错误(这将返回 Profile<void>
)。
我可以使用throw err;
代替return Promise.reject(err);
行,但有时我想使用Promise.reject
模式(例如,如果我想在返回之前做更多事情)。
我感觉我在 Promise / async 方面遗漏了一些东西,但我找不到遵循这种模式的类型示例。
...请注意,如果我使用完整的 Promise 模式,它可以正常工作:
doSomething('12')
.then( (something) => //do stuff)
.catch( (err) => //handle error);
我应该只使用throw
而忘记Promise.reject
吗?如果我使用throw
,.catch()
会被正确触发吗?
【问题讨论】:
...我已经回答了我的部分问题:“如果我使用 throw 会适当地触发 .catch() 吗?” - 是的,编写一些测试代码表明确实如此。我猜抛出的错误会变成异步函数中被拒绝的承诺。不过,我仍然很想知道如何在这种情况下使用 Promise.reject (特别是我的打字错误问题)。 重点是可以使用throw
。请使用throw
,因为您所拥有的模式非常混乱。
我不同意它是模式的混合 - 必须使用 throw
以及返回承诺似乎更像是模式的混合。使用 Promise.resolve 和 Promise.reject 似乎是对模式的一致使用。
【参考方案1】:
首先不返回承诺是我通常实现异步等待模式的方式:
export async function doSomething(userId:string) : Promise<ISomething>
let something: ISomething = ;
try
something.user = await UserDocument.findById(userId);
something.pet = await PetDocument.findOne(ownerId:userId);
return something;
catch (err)
console.log("I would do some stuff here but I also want to have the caller get the error.");
throw(err);
因此,如果您不必进行中间清理,则可以将其简化为:
export async function doSomething(userId:string) : Promise<ISomething>
let something: ISomething = ;
something.user = await UserDocument.findById(userId);
something.pet = await PetDocument.findOne(ownerId:userId);
return something;
并且拥有
后续等待的函数捕获异常或
调用函数处理被拒绝的承诺
【讨论】:
【参考方案2】:如果您不想使用 Promise.reject
和 Promise.resolve
,这一切正常,但如果您这样做了 - 这是一个简单的解决方法。
去掉签名中的| void
,将拒绝返回改为return Promise.reject<ISomething>(err);
。有效!
这是问题的修改版本:
export async function doSomething(userId:string) : Promise<ISomething>
let something: ISomething = ;
try
something.user = await UserDocument.findById(userId);
something.pet = await PetDocument.findOne(ownerId:userId);
return Promise.resolve(something);
catch (err)
console.log("I would do some stuff here but I also want to have the caller get the error.");
return Promise.reject<ISomething>(err);
【讨论】:
这是对编译器的谎言,因为Promise.reject
没有返回ISomething
类型的东西。以上是关于在 TypeScript 中使用 Promises 的异步函数的正确错误模式的主要内容,如果未能解决你的问题,请参考以下文章
我期望从 API 响应中接收一组对象,但在使用 TypeScript 的 React 中获得一组 Promise
Learining TypeScript TypeScript 简介
Learining TypeScript TypeScript 简介