调用 API 端点的最佳实践

Best Practice of calling an API endpoint

调用 API 端点时 returning 的最佳做法是什么? return 整个回复最好吗?让我们举一个简单的例子。比方说我正在建立一个网上商店。

我调用的端点需要2个参数,方法是POST。产品编号和数量。

每个产品都有库存。所以当我填写“50”作为数量时,我会收到这样的错误响应:

状态:405 方法不允许

{
    "code": "cocart_quantity_invalid_amount",
    "message": "Quantity must be 26 or lower.",
    "data": {
        "status": 405
    }
}

这很好,很清楚。

如果 Status 是 200 OK,我会得到一大堆数据。在下面的代码中,我 return 一个 Cart 对象。或者如果我 return 包含错误消息的 Message 对象更好? return 一条消息 'Item successfully added to cart'?

问题是,我不能在调用失败时 return 错误消息,而在调用成功时 return 购物车。什么是最佳实践,为什么?如果能用javascript代码解释一下就好了。

在下面的代码示例中,我在 if 和 else 语句中 return 购物车。如果我是正确的,这不是最佳实践...

class Message {
  String message;

  Message({required this.message});

  // Make a message object from retrieved json
  factory Message.fromJson(Map<String, dynamic> json) {
    return Message(message: json['message']);
  }
}
Future<Cart> addToCart(productId, quantity) async {
    String token = await Auth().getToken();
    var response = await http.post(
      Uri.parse('https://websitename.nl/wp-json/cocart/v2/cart/add-item'),
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'Authorization': token,
      },
      body: <String, String>{"id": productId, "quantity": quantity},
    );
    if (response.statusCode == 200) {
      // String data = response.body;
      // var decodedData = json.decode(data);

      return Cart.fromJson(jsonDecode(response.body));
    } else {
      return Cart.fromJson(jsonDecode(response.body));
    }
  }

那么最佳做法是什么?为什么?

  1. 用 'Succeeded' 或 'the error message itself'
  2. return 消息对象更好吗
  3. 即使调用不成功,return购物车对象是否更好。
  4. 或者你们有什么推荐的吗?很高兴听到答案。我自己找不到明确的答案,这就是为什么我在这个 post.
  5. 中提问的原因

所以你有一个方法,你想在方法成功时 return 一些东西(Cart),在方法失败时想一些东西(Message),我会告诉你两种可能的方法来做到这一点:

1。制作一个封装两个对象的 class:

这里的想法是有一个 class 包含关于成功与否的信息以及购物车,这看起来像这样:

class ApiResult {
  String? errorMessage;
  int code;
  Cart? cart;

  bool get hasError => code != 200;
  bool get hasData => cart != null;

  ApiResult({
    this.errorMessage
    this.cart,
    required this.code
  }): assert(
      (code!=200 && errorMessage!=null)
      || (code==200 && cart!=null)
    );
}

所以上面 class 三个重要的东西,一个可以为 null 的购物车,一个可以为 null 的消息,以及响应的状态代码,所以我们知道要检查哪个。为了简单起见,我们还可以添加几个命名构造函数:

class ApiResult {
  String? errorMessage;
  int code;
  Cart? cart;

  bool get hasError => code != 200;
  bool get hasData => cart != null;

  ApiResult({
    this.errorMessage
    this.cart,
    required this.code
  }): assert(
      (code!=200 && errorMessage!=null)
      || (code==200 && cart!=null)
    );

  ApiResult.success({
    required int code,
    required Cart cart,
  }): ApiResult(cart: cart, code: code);

  ApiResult.error({
    required int code,
    required String message
  }): ApiResult(message: message, code: code);
}

然后在您的 API 电话上:

Future<ApiResult> addToCart(productId, quantity) async {
    String token = await Auth().getToken();
    var response = await http.post(
      Uri.parse('https://websitename.nl/wp-json/cocart/v2/cart/add-item'),
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'Authorization': token,
      },
      body: <String, String>{"id": productId, "quantity": quantity},
    );
    if (response.statusCode == 200) {
      return ApiResult.success(code: 200, cart: Cart.fromJson(jsonDecode(response.body)));
    } else {
      var data = jsonDecode(response.body);
      return ApiResult.error(code: response.statusCode, message: data['message']);
    }
  }

在写完整个 class 之后,我意识到你可以不用 code 参数,只使用消息和购物车,这可能会大大简化代码。

2。抛出错误信息:

您的第二个选择是在调用该方法时使用 try catch,并抛出错误消息,如下所示:

Future<Cart> addToCart(productId, quantity) async {
    String token = await Auth().getToken();
    var response = await http.post(
      Uri.parse('https://websitename.nl/wp-json/cocart/v2/cart/add-item'),
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'Authorization': token,
      },
      body: <String, String>{"id": productId, "quantity": quantity},
    );
    if (response.statusCode == 200) {
      return Cart.fromJson(jsonDecode(response.body));
    } else {
      throw Message.fromJson(jsonDecode(response.body));
    }
  }

这样调用方法时:

try {
  await addToCart(...);
} on Message catch (e) {
  // do something about the error
}

上述两种解决方案各有利弊,如果我们谈论的是“最佳实践”,那么第二种选择可能更好,因为它按照预期的方式使用 try-catch,但在我看来两者都不错。