在 Dart 中因参数无效(例如登录)而引发异常?

Ted*_*nry 3 dart flutter

signIn我在 Dart 程序中有一个异步函数,它接受usernamepassword字符串参数。该函数调用远程服务器,如果用户名和/或密码丢失或不正确,服务器会使用会话令牌或验证消息进行响应。

目前我已经通过回调实现了这一点。服务器响应后会调用适当的回调。不需要await

signIn(username, password, onSuccess, onFailure);
Run Code Online (Sandbox Code Playgroud)

我对 Dart 的了解越多,我觉得上面的内容并不是真正的 Dart 做事方式。我应该awaittryand结合使用吗catch?像下面这样的东西吗?

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.
}
Run Code Online (Sandbox Code Playgroud)

登录凭据可能无效。处理它们是正常的程序流程。我被教导永远不要将 try/catch 用于常规的、预期的程序流程。Dart 语言似乎鼓励使用异常处理,尤其是与await.

来自错误类文档[强调我的。]

如果在调用函数之前无法检测到条件,则被调用的函数不应抛出错误。它仍然可能抛出一个值,但调用者必须捕获抛出的值,从而有效地使其成为替代结果而不是错误。抛出的对象可以选择实现 Exception 来记录它代表异常但不是错误的发生,但它除了记录之外没有其他作用。

实现这个的最好的 Dart 方法是什么?

cre*_*not 6

错误与异常

您链接的文档本质上说该类Error应该用于您定义的“常规的预期程序流”,Exception应该使用。这也意味着Dart 中 鼓励try使用-catch来解决此类情况。

从文档来看,Errors 应该用于“程序员应该避免的程序故障”,即意外的程序流程。然而,Exception“旨在向用户传达有关故障的信息,以便可以通过编程方式解决错误”,即预期的程序流程

为了实现异常,您必须扩展Exception并创建自己的异常类。Dart 通过不提供对传递给常规Exception.

不鼓励直接创建Exception实例new Exception("message"),并且仅作为开发期间的临时措施,直到库使用的实际异常完成为止。

例子

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.
  }
}
Run Code Online (Sandbox Code Playgroud)

我创建的目的InvalidCredentialsException是处理传递给 的无效凭据signIn。对于message(你可以随意称呼它),我只是使用 anenum来区分无效username和无效password(可能不是你想要做的,它应该只是解释这个概念)。

当使用try-处理它时catch,您可以catch为不同类型创建不同的 -block。在我的示例中,我用于on InvalidCredentialsException响应程序流中的预期异常,另一种on Error用于响应意外失败。

当使用onforcatch语句时,您面临着无法捕获其他类型异常的风险,这些异常随后将被抛出。如果你想防止这种情况发生,你可以使用另一个块来处理通用异常,即或者在末尾on Exception有一个通用- 块( )。catchcatch (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});
}
Run Code Online (Sandbox Code Playgroud)

  • @TedHenry我考虑过将其包含在原始答案中,但是,Dart `switch` 语法很庞大,对于两种情况来说不太好。我同意你的观点,这将是“最 Dart”的方式,所以我会将其包含在答案中。 (2认同)