首页 > 解决方案 > Dart HttpClient 未读取完整响应

问题描述

我在使用 dart HttpClient 时遇到了一个奇怪的问题,它似乎在“完成”之前没有读取完整的响应。这是我的代码:

HttpClient client = new HttpClient();
client.connectionTimeout = Duration(seconds: 60);
Completer<MealPlan> completer = new Completer();

RecipeSearchFilter filter = new RecipeSearchFilter();
filter.restrictions = intolerances.map((intolerance) => intolerance.name).toList();
MealPlan mealPlan;
client
    .getUrl(Uri.parse(
    "https://myUrl.com/api/meal-plans?filter=${jsonEncode(filter)}"))
.then((HttpClientRequest request) {
  request.headers.set("Authorization", "Bearer $idToken");
  return request.close();
}).then((HttpClientResponse response) {
  response.transform(utf8.decoder).listen((contents) {
    Map<String, dynamic> contentMap = jsonDecode(contents);
    mealPlan = MealPlan.fromJson(contentMap);
  }, onDone: () => completer.complete(mealPlan));
});

return completer.future;

这是我的应用程序包含的最密集的功能,因此这个特定的 API 本身通常需要 6-8 秒才能完全完成,因为幕后发生了很多事情。响应不大(~60KB)。使用 Postman 进行完全相同的调用,我可以看到它确实按预期返回了所有内容,但是如果我查看}).then((HttpClientResponse response) {块内的响应,它只包含非常小的部分响应。我不确定我在这里做错了什么,但我猜我已经错误地配置了 HttpClient 。

标签: flutterdart

解决方案


问题是您的响应将由流分段传递。在通过 utf8 解码器传递这些块之后,您应该在尝试对其进行 json 解码之前将它们形成一个字符串。目前,您尝试 json 解码第一个块而不等待其余部分。

package:http使用which 包装器要容易得多HttpClient,并且可以为您完成很多繁重的工作。此外,使用async/await语法而不是.then.

使用async您可以编写的方法,例如:

void getPlan(Map filter, String idToken) async {
  var response = await http.get(
    Uri.parse('https://myUrl.com/api/meal-plans?filter=${jsonEncode(filter)}'),
    headers: <String, String>{
      'Authorization': 'Bearer $idToken',
    },
  );

  return MealPlan.fromJson(json.decode(response.body));
}

如果真的要控制连接超时,需要自己传入HttpClient,如下:

  var client =
      http.IOClient(HttpClient()..connectionTimeout = Duration(seconds: 60));

  var response = await client.get(
    //etc

推荐阅读