我在Dart程序中有一个异步函数signIn
,该函数带有username
和password
字符串参数。该函数调用远程服务器,如果用户名和/或密码丢失或不正确,则服务器将使用会话令牌或验证消息进行响应。
目前,我已通过回调实现了此功能。服务器响应后,将调用适当的回调。不需要await
。
signIn(username, password, onSuccess, onFailure);
我对Dart的了解越多,我觉得以上内容并不是Dart的实际工作方式。我应该结合使用await
和try
的{{1}}吗?像下面这样?
catch
可能是无效的登录凭据。处理它们是正常的程序流程。我被教导永远不要对常规的预期程序流使用try / catch。似乎Dart语言鼓励使用异常处理,尤其是与try {
sessionToken = await signIn(username, password);
// navigate from the sign in screen to the home screen.
} on InvalidParams catch (e) {
// e contains the server's validation messages
// show them to the user.
}
结合使用。
来自Error class documentation [强调我。]
如果在调用函数之前无法检测到条件,则 调用的函数不应引发错误。它可能仍会抛出一个值, 但呼叫者将必须捕获抛出的值,有效地使 它是替代结果,而不是错误。抛出的物体可以 选择实施Exception以记录它表示一个 异常但不是错误的发生,但是没有其他影响 比文档更重要。
实现Dart的最佳方式是什么?
答案 0 :(得分:1)
您链接的文档从本质上说,Error
class不应用于定义为“正常的预期程序流” 的内容,而应使用Exception
。这也意味着在Dart中鼓励使用try
-catch
处理此类情况。
从文档中,应将 Error
用于“程序员应避免的程序故障”,即 意外 < / strong> 程序流程。但是, Exception
是“旨在向用户传达有关故障的信息,以便可以通过编程方式解决错误”,即 expected 程序流程。
为了实现异常,您将必须扩展Exception
并创建自己的异常类。 Dart通过不提供对传递到常规Exception
的消息的访问来实施此操作。
不建议直接使用
new Exception("message")
创建Exception的实例,并且仅在开发过程中将其作为临时措施包括在内,直到完成库使用的实际异常为止。
enum InvalidCredentials { username, password }
class InvalidCredentialsException implements Exception {
final InvalidCredentials message;
const InvalidCredentialsException({this.message});
}
function() {
try {
await signIn(username, password);
} on InvalidCredentialsException catch (e) {
switch (e.message) {
case InvalidCredential.username:
// Handle invalid username.
break;
case InvalidCredential.password:
// Handle invalid password.
break;
}
} on Error catch (e) {
print(e);
} catch (e) {
// Handle all other exceptions.
}
}
我创建了InvalidCredentialsException
来处理传递给signIn
的无效凭证。对于message
(您可以随心所欲地调用它),我只是使用enum
来区分无效的username
和无效的password
(可能不是您想要的)要这样做,应该只解释一下这个概念。
使用try
-catch
处理它时,可以为不同类型创建不同的catch
块。在我的示例中,我使用on InvalidCredentialsException
响应程序流中的 expected 异常,并使用另一个on Error
响应 expected 失败。
在on
语句中使用catch
时,您冒着无法捕获其他类型异常的风险,然后将其抛出。如果要防止这种情况,则可以为通用异常设置另一个块,即on Exception
,或者在结尾(catch
)后面仅具有通用catch (e)
块。
如果您希望能够打印出异常,则可能希望覆盖异常类中的toString
。
此外,您显然可以根据自己的意愿传输尽可能多的信息,例如(根据上面的代码修改):
// ...
throw InvalidCredentialsException(cause: InvalidCredentials.password, message: password);
// ...
class InvalidCredentialsException implements Exception {
final InvalidCredentials cause;
final String message;
const InvalidCredentialsException({this.cause, this.message});
}