如何在Dart中从Future返回错误?

67

在我的Flutter应用程序中,我有一个处理HTTP请求并返回解码数据的Future。但是,如果状态码!= 200,我希望能够发送错误,并使用.catchError()处理程序获取它。

这是我的Future代码:

Future<List> getEvents(String customerID) async {
  var response = await http.get(
    Uri.encodeFull(...)
  );

  if (response.statusCode == 200){
    return jsonDecode(response.body);
  }else{
    // I want to return error here 
  }
}

当我调用这个函数时,我希望能够获得以下错误信息:

getEvents(customerID)
.then(
  ...
).catchError(
  (error) => print(error)
);
5个回答

112

抛出错误/异常:

您可以使用 returnthrow 来抛出错误或异常。

  • 使用 return
    Future<void> foo() async {
      if (someCondition) {
        return Future.error('FooError');
      }
    }
    
  • 使用 throw:
    Future<void> bar() async {
      if (someCondition) {
        throw Exception('BarException');
      }
    }
    

捕获错误/异常:

您可以使用catchErrortry-catch块来捕获错误或异常。

  • 使用catchError
    foo().catchError(print);
    
  • 使用 try-catch:
    try {
      await bar();
    } catch (e) {
      print(e);
    }
    

4
我想看到的是这个答案,抛出异常会使日志显示“UNCAUGHT EXCEPTION”... - cs guy
好的,例子在哪里?我的用例是使用await。不确定如何在await中使用catchError,不太清楚。 - Toskan
@Toskan,你能在DartPad上分享一下你的最小代码吗? - CopsOnRoad
@Toskan 将其包裹在 try 块中。这就是为什么有两种形式。 - Hari Honor
如果函数返回return Future.error,那么我就不能使用await来捕获错误。这对我来说似乎是一个弱点。 - Toskan

39

你可以使用 throw

Future<List> getEvents(String customerID) async {
  var response = await http.get(
    Uri.encodeFull(...)
  );

  if (response.statusCode == 200){
    return jsonDecode(response.body);
  }else{
    // I want to return error here 
       throw("some arbitrary error"); // error thrown
  }
}

2
我在throw("some arbitrary error");上遇到了“异常已发生”的问题。 - Augusto
1
我一直很困惑为什么提问者会标记这个答案。但是如何从then()块抛出错误并在调用方Future的catchError()块中捕获它呢?就像问题中那样。 - stackunderflow
@anmol.majhail:如果我想使用await,而不是使用catch,我该如何检查结果和错误? - Abhishek Thapliyal

3

解决这个问题的另一种方法是使用 dartz 包。

以下是使用该包的示例:

import 'package:dartz/dartz.dart';

abstract class Failure {}
class ServerFailure extends Failure {}
class ResultFailure extends Failure {
  final int statusCode;
  const ResultFailure({required this.statusCode});
}

FutureOr<Either<Failure, List>> getEvents(String customerID) async {
  try {
    final response = await http.get(
      Uri.encodeFull(...)
    );

    if (response.statusCode == 200) {
      return Right(jsonDecode(response.body));
    } else {
      return Left(ResultFailure(statusCode: response.statusCode)); 
    }
  }
  catch (e) {
    return Left(ServerFailure());  
  }
}

main() async {
  final result = await getEvents('customerId');
  result.fold(
    (l) => print('Some failure occurred'),
    (r) => print('Success')
  );
}

1

如果您想读取错误对象,可以像这样返回错误数据:

response = await dio.post(endPoint, data: data).catchError((error) {
  return error.response;
});
return response;

0

//POST

Future<String> post_firebase_async({String? path , required Product product}) async {
    final Uri _url = path == null ? currentUrl: Uri.https(_baseUrl, '/$path');

    print('Sending a POST request at $_url');

    final response = await http.post(_url, body: jsonEncode(product.toJson()));
    if(response.statusCode == 200){
      final result = jsonDecode(response.body) as Map<String,dynamic>;
      return result['name'];
    }
    else{
      //throw HttpException(message: 'Failed with ${response.statusCode}');
      return Future.error("This is the error", StackTrace.fromString("This is its trace"));
    }

  }

以下是如何调用的方法:

  final result = await _firebase.post_firebase_async(product: dummyProduct).
  catchError((err){
    print('huhu $err');
  });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接