如何在HTTP API将来的请求中返回错误对象

时间:2019-11-04 05:04:37

标签: http flutter dart

我正在使用BLOC模式,所以我的查询是如何在HTTP请求后返回一些错误。 假设如果API返回200作为状态代码,那么我可以返回特定的模型,如果从API返回的错误(例如302、404 401 ...),我可以提到该模型,以此类推,如何处理并返回UI以显示错误消息

Future<SampleModel> getSomeDetails(String ID) async {
    var response =
    await http.get(someURL,
        headers: {'Content-type': 'application/x-www-form-urlencoded',});
    if (response.statusCode == 200) {
      return SampleModel.fromJson(json.decode(response.body));
    } else {
      throw Exception('Failed to load post');// return the error to UI
    }
  }

PS:我也在使用观察者模式

3 个答案:

答案 0 :(得分:1)

您可以返回:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char *argv[]) {
    int c=1,i,s;
    char a[1000];
    fgets(a,1000,stdin);
    for(i=0;i<strlen(a);i++){
        if(a[i]=='\n'){
            a[i]='\0';
        }
    } 
    for(i=0;i<strlen(a);i++){
        if(a[i]==','){
            c++;
        }
    }
    char **b;
    b=(char**)malloc(sizeof(char)*c); 
    for(i=0;i<c;i++){
        b[i]=(char*)malloc(sizeof(char)*100);
    }
    strcpy(b[0],strtok(a,","));
    for(i=1;i<c;i++){
        strcpy(b[i],strtok(NULL,","));
    }
    char **d;
    d=(char**)malloc(sizeof(char*)*c);
    for(i=0;i<c;i++){
        d[i]=(char*)malloc(sizeof(char)*strlen(b[i]));
        for(s=0;s<strlen(b[i]);s++){
            d[i][s]=b[i][strlen(b[i])-s-1];
        }
    }
    printf("%s",d[0]);
    for(i=1;i<c;i++){
        printf(",%s",d[i]);
    }
    for(i=0;i<c;i++){
        free(b[i]);
        free(d[i]);
    }
    free(b);
    free(d);
    return 0;
}

然后您可以执行以下操作:

Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(Intent.EXTRA_TEXT,"Extra text or Link that you want to add");
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Technical Speaks");
startActivity(Intent.createChooser(sharingIntent, "Share via"));

Future.error("Error message").

答案 1 :(得分:1)

由于您使用的是bloc,因此可能会有某种流向其中添加数据:

StreamController<int> data = new StreamController<int>();

您可能使用StreamBuilder侦听该流上的事件并显示数据。您还可以侦听流中的错误:

StreamBuilder<int>(
  builder: (context, snapshot) {
    if (snapshot.hasError) {
      // Show error message
      return Text('An error occured');
    } else if (snapshot.hasData) {
      // Show data
      return Text('${snapshot.data}');
    }

    // No data, show loader
    return CircularProgressIndicator();
  },
  stream: data.stream,
),

所以您只能在流中出现错误:

// Adding an error to the stream
data.addError('Failed to load post');

答案 2 :(得分:0)

我正在使用我自己的API调用机制,如下所示,您可以管理所有类型的异常。

api_handler.dart

import 'dart:async';
import 'dart:convert';

import 'package:connectivity/connectivity.dart';
import 'package:package_name/base/api/api_exception.dart';
import 'package:package_name/utils/app_constatns.dart';
import 'package:package_name/utils/log_utils.dart';
import 'package:package_name/utils/preference_utils.dart';
import 'package:package_name/utils/strings.dart';
import 'package:http/http.dart' as http;

class ApiHandler {
  // next three lines makes this class a Singleton
  static ApiHandler _instance = new ApiHandler.internal();
  final JsonDecoder _decoder = new JsonDecoder();

  ApiHandler.internal();

  factory ApiHandler() => _instance;

  Future<bool> isInternetConnected() async {
    var connectivityResult = await (Connectivity().checkConnectivity());
    if (connectivityResult == ConnectivityResult.mobile ||
        connectivityResult == ConnectivityResult.wifi) {
      return true;
    }
    return false;
  }

  Future<dynamic> get(String url) async {
    LogUtils.d("====URL GET Call:   $url");
    String token = PreferenceUtils.getString(AppConstants.LOGGED_IN);

    // ignore: unrelated_type_equality_checks
    var isConnected = await isInternetConnected();
    if (isConnected != true) {
      return Future.error(ApiException(Strings.internetNotConnected));
    }
    return http.get(url, headers: {"Authorization": "Bearer $token"}).then(
        (http.Response response) {
      final int statusCode = response.statusCode;
      LogUtils.d("====response ${response.body.toString()}");

      if (statusCode < 200 || statusCode >= 400 || json == null) {
        throw new ApiException(jsonDecode(response.body)["message"]);
      }
      return _decoder.convert(response.body);
    });
  }

  Future<dynamic> post(String url, {body, encoding}) async {
    LogUtils.d("====URL POST Call:   $url");
    LogUtils.d("====body :   $body");
    String token = PreferenceUtils.getString(AppConstants.LOGGED_IN);
    var isConnected = await isInternetConnected();
    if (isConnected != true) {
      return Future.error(ApiException(Strings.internetNotConnected));
    }

    return http.post(url,
            body: json.encode(body),
            headers: { 'Content-type': 'application/json',
              'Accept': 'application/json',
              "Authorization": "Bearer $token"},
            encoding: encoding)
            .then((http.Response response) {
      final int statusCode = response.statusCode;
      LogUtils.d("====responseBody ${response.body.toString()}");
      LogUtils.d("====responseStatusCode ${response.statusCode}");

      if (statusCode < 200 || statusCode >= 400 || json == null) {
        throw new ApiException(jsonDecode(response.body)["message"]);
      }
      return _decoder.convert(response.body);
    });
  }
}

api_exception.dart

class ApiException implements Exception {
  String errorMsg = "Server not respond";

  ApiException(String error) {
    this.errorMsg = error ?? "Server not respond";
  }
}

api_manager.dart

import 'dart:convert';
import 'dart:io';

import 'package:flutter_my_recipes/utils/log_utils.dart';
import 'package:flutter_my_recipes/utils/preference_utils.dart';
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart';

import 'api_handler.dart';

class ApiManager {
  // next three lines makes this class a Singleton
  static ApiManager _instance = new ApiManager.internal();

  ApiManager.internal();

  factory ApiManager() => _instance;

  static ApiHandler _handler;

  static void init() {
    _handler = new ApiHandler();
  }

  static Future<LoginRes> loginApi(Map<String, dynamic> json) {
    return _handler.post(UrlConstants.LOGIN_URL, body: json).then((res) {
      return LoginRes.fromJson(res);
    });
  }
}

API调用示例:-

void loginApiCall(BuildContext context, LoginReq _signInReq) {
    ApiManager.loginApi(_signInReq.toJson()).then((signInResponse) {
      notifyListeners();
      print("===Success $signInResponse");
      PreferenceUtils.setString(
          AppConstants.USERDATA, JsonCodec().encode(signInResponse.toJson()));
      PreferenceUtils.setString(AppConstants.LOGGED_IN, signInResponse.token);
      isLoading = false;
      Navigation.pushAndRemoveUntil(context, Screens.HOME);
    }).catchError((onError) {
      isLoading = false;
      notifyListeners();
      print("===onError $onError");
      ProcessDialog.closeLoadingDialog();
      Toast.show(onError.errorMsg, context, duration: 2);
    });
  }

您必须在main.dart文件中调用ApiManager初始化方法,以便可以在整个应用程序中使用Apimanager Instance。