패키지, 저장소 및 앱 카테고리 검색

패키지 상세v5.3.0

multiple_result

dart의 여러 결과. dartz의 Either와 Kotlin의 sealed 클래스에 영감을 받음

AndroidiOSWebmacOSWindowsLinux
30일 다운로드
4.5만
좋아요
174
Pub 점수
160

패키지 설치

flutter pub add multiple_result

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

Multiple_result는 dartz의 Either와 Kotlin의 sealed 클래스에 영감을 받아 타입 안전하게 여러 가능한 결과를 처리할 수 있는 강력한 방식을 제공하는 Dart 패키지입니다. 개발자들이 다양한 성공 또는 실패 상태를 가진 복잡한 결과 유형을 모델링할 수 있게 해주며, 코드의 명확성과 오류 처리를 향상시킵니다. 이 패키지는 체계적인 패턴 매칭을 지원하며, 모든 주요 플랫폼에서 사용하도록 설계되어 Flutter 및 기타 Dart 애플리케이션에서 함수형 프로그래밍에 이상적입니다.

사용 사례

  • API에서 여러 성공 또는 오류 상태 처리
  • 명확한 결과 유형을 사용한 상태 관리 구현
  • 명시적인 결과를 통해 회복력 있는 비즈니스 로직 구축
  • Dart에서 함수형 프로그래밍 패턴 지원
  • 다양한 결과를 가진 비동기 작업 관리

주요 기능

  • 다양한 결과 유형을 지원합니다
  • 포괄적인 패턴 매칭
  • 타입 안전한 결과 처리
  • Kotlin sealed 클래스와 dartz Either 에서 영감을 받음
  • 크로스 플랫폼 호환성

적합한 대상

  • Dart에서 함수형 프로그래밍을 사용하는 개발자
  • 타입 안전성과 오류 처리를 우선시하는 팀
  • 구조화된 결과 관리를 필요로 하는 플러터 앱
  • 복잡한 상태 전이를 가진 프로젝트

고려 사항

  • 함수형 개념을 이해해야 합니다
  • 간단한 경우에 부가적인 보일러플레이트가 증가할 수 있습니다
  • 복잡한 워크플로우를 가진 대규모 애플리케이션에 가장 적합
  • 다중 변형이 없는 기본 성공/실패 시나리오에는 적합하지 않음

원본 README

연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.

multiple_result

A Result package for Dart inspired by dartz's Either type and Kotlin's sealed classes.

This package is perfect for those who just want the multiple results functionality from dartz. 👌

Using the Result type:

In your function signature, declare it to return a Result type:

Result getSomething();

Then specify the Success and Error types:

Result<String, Exception> getSomething() {

}

When returning from the function, simply use:

return Success('Success!');

or

return Error(Exception('Some error happened...'));

A complete function looks like this:

Future<Result<String, Exception>> getSomething() async {
    
    try {
      final response = await _api.get('/foo');
      final data = response.data['bar'];
      return Success(data);
    } catch(e) {
      return Error(e);
    }
}
Handling Results
Using switch:
void main() {
  final result = getSomething();
  switch(result) {
    case Success():
      print("${result.success}");
      break;
    case Error():
      print("${result.error}");
      break;
  }
}

Or with Switch Expression:

  final result = await getSomething();
  final output = switch (result) {
    Success(success: var s) => processSuccess(s),
    Error(error: var e) => handleError(e)
  };
Using when:
void main() {
    final result = await getSomething();
    final String message = result.when(
        (data) {
          // handle the success here
          return "Successfully fetched data: $data";
        },
        (error) {
          // handle the error here
          return "error: $error";
        },
    );
}
Using if case:
void main() {
  final result = getSomething();
  if(result case Success()) {
    // access to .success value
    print("${result.success}");
  }
}
Using whenSuccess or whenError
    final result = getSomethingPretty();
    // Note that [whenSuccess] or [whenError] will only be executed if
    // the result is a Success or an Error respectively. 
    final output = result.whenSuccess((name) {
        // handle here the success
        return "";
    });
    
    final result = getSomethingPretty();
    
    // If [result] is NOT an Error, this [output] will be null.
    final output = result.whenError((exception) {
        // handle here the error
        return "";
    });
Using getOrThrow

You can use getOrThrow to get the value when you're sure that the result is a Success. Be aware that calling this method when the result is actually an Error will throw a SuccessResultNotFoundException.

    final result = await getSomething();

    if (result.isSuccess()) {
      // Here, you can "safely" get the success result as it was verified in the previous line.
      final mySuccessResult = result.getOrThrow();
    }
Using tryGetSuccess
void main() {
    final result = getSomethingPretty();

    String? mySuccessResult;
    if (result.isSuccess()) {
      mySuccessResult = result.tryGetSuccess();
    }
}
Using tryGetError
void main() {
    final result = getSomethingPretty();

    Exception? myException;
    if (result.isError()) {
      myException = result.tryGetError();
    }
}

Using getBoth

The getBoth method returns a record (Dart's named tuple) containing both the success and error values of a Result. Only one of these will be non-null, depending on whether the result is a Success or an Error.

  • If the result is a Success, the success field will contain the value, and error will be null.
  • If the result is an Error, the error field will contain the error, and success will be null.

This is useful for destructuring or pattern matching without having to check the type explicitly.

Example:

void main() {
  final result = getSomething();
  final (:success, :error) = result.getBoth();
  
  if (success != null) {
    print("Success: $success");
  } else {
    print("Error: $error");
  }
}

Transforming Results

The Result class provides several methods for transforming values while preserving the success/error structure:

Using map

The map method transforms both the success and error values of a Result:

Result<int, Exception> result = fetchNumber();
Result<String, String> transformed = result.map(
  successMapper: (number) => number.toString(),
  errorMapper: (exception) => exception.toString()
);
Using mapSuccess

The mapSuccess method transforms only the success value, preserving any error:

Result<int, Exception> result = fetchNumber();
Result<String, Exception> transformed = result.mapSuccess(
  (number) => number.toString()
);
Using mapError

The mapError method transforms only the error value, preserving any success:

Result<int, Exception> result = fetchNumber();
Result<int, String> transformed = result.mapError(
  (exception) => exception.toString()
);
Using flatMap

The flatMap method is powerful for chaining operations that can fail. Unlike mapSuccess which wraps the returned value in a Result, flatMap expects your function to return a Result directly:

Result<int, String> fetchNumber() => Success(5);

Result<String, String> parseNumber(int n) {
  if (n > 0) {
    return Success(n.toString());
  } else {
    return Error("Cannot parse negative numbers");
  }
}

// Chain operations that might fail
Result<String, String> result = fetchNumber().flatMap(
  (number) => parseNumber(number)
);

The key difference between mapSuccess and flatMap:

  • mapSuccess takes a function that returns a value T and wraps it in a Result
  • flatMap takes a function that returns a Result directly, avoiding nested Results
Using Result.tryCatch

Replace try/catch blocks with Result.tryCatch to convert a throwing operation directly into a Result:

final result = Result.tryCatch(
  () => int.parse(userInput),
  (error, stackTrace) => ParseError(error.toString()),
);
// result is Success(42) or Error(ParseError(...))
Using getOrElse

Provide a fallback value computed from the error instead of throwing:

final value = result.getOrElse((error) => defaultValue);
Using onSuccess / onError

Run side effects (e.g. logging) in the middle of a chain without breaking it:

result
    .onSuccess((data) => logger.info('Got $data'))
    .onError((error) => logger.error('Failed: $error'))
    .mapSuccess((data) => data.toUpperCase());
Using flatMapError / recover

Handle errors and recover into a new Result, symmetric to flatMap:

final result = fetchUser(id)
    .flatMapError((e) => fetchUserFromCache(id));

// or with the alias:
final result = fetchUser(id)
    .recover((e) => fetchUserFromCache(id));
Using swap

Convert a Success into an Error and vice versa — useful for inverting validation logic:

final inverted = result.swap();
// Success('x') becomes Error('x'), Error(e) becomes Success(e)

Async Results with AsyncResult

AsyncResult<S, E> is a zero-cost wrapper around Future<Result<S, E>> using Dart extension types. It lets you chain transformations on async results fluently without awaiting at each step.

// Wrap a Future<Result> as AsyncResult
AsyncResult<User, ApiError> fetchUser(int id) =>
    AsyncResult(api.get('/users/$id').then((r) => r.toResult()));

// Chain operations without intermediate awaits
final greeting = await fetchUser(42)
    .mapSuccess((user) => user.name.toUpperCase())
    .onError((e) => logger.error('Failed: $e'))
    .getOrElse((_) => 'Anonymous');

Use AsyncResult.tryCatch to wrap a potentially-throwing async function:

final result = AsyncResult.tryCatch(
  () async => await api.fetchUser(id),
  (error, stack) => NetworkError(error.toString()),
);

Use flatMapAsync to chain operations that are themselves async:

final result = fetchUser(42)
    .flatMapAsync((user) => fetchPosts(user.id));

Unit Type

Some results don't need a specific return value. Use the Unit type to signal an empty return:

    Result<Unit, Exception>

ResultOf

You may have noticed the ResultOf typedef. It represents a more readable alternative for Result.

카테고리

소스 저장소

이 패키지를 사용하는 프로젝트