代码之家  ›  专栏  ›  技术社区  ›  Ukonn Ra

像Scala'Try那样在Dart中优雅地处理错误`

  •  0
  • Ukonn Ra  · 技术社区  · 6 年前

    import 'package:validate/validate.dart';
    class AuthUser {
      final String email, token, username, bio, image;
    
      AuthUser(this.email, this.token, this.username, this.bio, this.image) {
        Validate.isEmail(this.email);
      }
    
      @override
      String toString() {
        return 'AuthUser{email: $email, token: $token, username: $username, bio: $bio, image: $image}';
      }
    }
    

    哪里 Validate.isEmail 匹配失败时将引发错误:

    static void matchesPattern(String input, RegExp pattern,[String message = DEFAULT_MATCHES_PATTERN_EX]) {
        if (pattern.hasMatch(input) == false) {
            throw new ArgumentError(message);
        }
    }
    
    static void isEmail(String input,[String message = DEFAULT_MATCHES_PATTERN_EX]) {
        matchesPattern(input,new RegExp(PATTERN_EMAIL),message);
    }
    

    现在我想用一种优雅的方式来更新这个类。 使用Scala时,我可以使用 Try(new AuthUser(...)) 和patten匹配。

    在达特,首先我试过RxDart,

    void main() {
      testWidgets('Counter increments smoke test', (WidgetTester tester) async {
        Observable.just(AuthUser("email", "token", "username", "bio", "img"))
            .doOnError((e, s) => print("oh no"))
            .listen((e) => print(e.toString()));
      });
    }
    

    而我想尝试未来,也失败了。

    有什么建议吗?

    2 回复  |  直到 6 年前
        1
  •  3
  •   SergGr    6 年前

    如果你能用 Future 这个建议有什么错: Using Future.sync() to wrap your code

    void main() {
      var f = Future.sync(() {AuthUser("email", "token", "username", "bio", "img"); });
      f.then((v) =>  print("Value: " + v.toString())).catchError((e) => print("Failure: " +e.toString()));
    }
    

    主要的诀窍是 Future.sync 有效地启用参数的延迟求值,但必须传递包装在函数中的参数。这实际上与Scala编译器的技巧相同 Try

        2
  •  1
  •   JRomero    6 年前

    如果您只需要基于是否发生异常而返回任一类型的基本功能,那么您可以轻松地创建如下实用程序类。

    Future.sync

    void main() {
      Try<Error, void> result = Try.it(() => Validate.isEmail("test-example.com"));
    
      if (result is Success) {
        print("Good");
      } else if (result is Failure) {
        print("Error: " + result.exception().toString());
      }
    }
    
    typedef TryExec<V> = V Function();
    
    abstract class Try<E extends Error, V> {
    
      static Try<E, V> it<E extends Error, V>(TryExec<V> fn) {
        try {
          return Try.success(fn());
        } catch (e) {
          return Try.failure(e);
        }
      }
    
      static Try<E, V> failure<E extends Error, V>(Error e) {
        return new Failure(e);
      }
    
      static Try<E, V> success<E extends Error, V>(V v) {
        return new Success(v);
      }
    }
    
    class Failure<E extends Error, V> extends Try<E, V> {
      final E _e;
      Failure(this._e);
    
      E exception() => _e;
    }
    
    class Success<E extends Error, V> extends Try<E, V> { 
      final V _v;
      Success(this._v);
    
      V value() => _v;
    }