我在使用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的配置不正确。
问题是您的响应将按流分批传递。在将这些块传递给utf8解码器之后,您应该将它们形成单个字符串,然后再尝试对其进行json解码。当前,您尝试对第一个块进行json解码,而无需等待其余的块。
package:http
的使用要容易得多,它是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