可重用的同步HttpClient请求

时间:2015-08-09 14:57:38

标签: dart httprequest dart-async dart-http

我需要一个可重用的函数来发出HTTP请求并在将响应作为String返回之前等待它完成。

这是主要功能:

main() async {
  var json;
  json = await makeRequest('https://...');
  print(json);
  print('*** request complete ***');
}

(第一种情况)这是发出HTTP请求的可重用函数:

makeRequest(String url) async {
  var request = await new HttpClient().postUrl(Uri.parse(url));

  // Includes the access token in the request headers.
  request.headers.add(...);

  // Waits until the request is complete.
  var response = await request.close();

  await for (var contents in response.transform(UTF8.decoder)) {
    return contents;
  }
}

这按预期工作,输出为:

// Response contents as a String...
*** request complete ***

(第二种情况)然后我尝试这样做但是没有用:

makeRequest(String url) async {
  var request = await new HttpClient().postUrl(Uri.parse(url));

  // Includes the access token in the request headers.
  request.headers.add(...);

  // Waits until the request is complete.
  var response = await request.close();

  var json = '';
  await response.transform(UTF8.decoder).listen((contents) {
    // At first I tried to return contents here, but then I added onDone().
    json += contents;
  }, onDone: () {
    return json;
  });

  return json;
}

我尝试使用listenasyncawait内定义函数,在contentslisten返回onDone(),但不是// Empty line. *** request complete *** // Waits a few seconds doing nothing before terminating... 输出是相同的:

Future<String> twitterRequest(String url) async {
  var request = await new HttpClient().postUrl(Uri.parse(url));

  // Includes the access token in the request headers.
  request.headers.add(...);

  // Waits until the request is complete.
  var response = await request.close();

  var json = '';
  await for (var contents in response.transform(UTF8.decoder)) {
    json += contents;
    // Putting a break here produces the same output but terminates immediately (as wanted).
  }

  return json;
}

有谁知道为什么第二种情况不起作用?

修改

更新代码后,它会执行它应该执行的操作,但在终止执行之前需要几秒钟:

// Prints response contents...
*** request complete ***
// Takes a few seconds before execution terminates. With the break the code terminates immediately.

输出:

HttpClient

EDIT2:

提交this issue on GitHub后,我发现library(reshape2) library(ggplot2) demo <- data.frame(cbind( ID = c(1:10), X = c(5.00, 1.03, 1.26, 2.03, 0.99, 4.24, 5.00, 5.00, 2.83, 5.00), Y1 = c(0.17, 0.84, 0.79, 0.59, 0.85, 0.22, 0.17, 0.17, 0.40, 0.17), Y1_lci = c(0.16, 0.81, 0.76, 0.56, 0.82, 0.22, 0.16, 0.16, 0.39, 0.16), Y1_uci = c(0.18, 0.87, 0.82, 0.61, 0.88, 0.23, 0.18, 0.18, 0.41, 0.18), Y2 = c(0.14, 0.85, 0.80, 0.59, 0.86, 0.20, 0.14, 0.14, 0.38, 0.14), Y2_lci = c(0.11, 0.83, 0.77, 0.54, 0.84, 0.16, 0.11, 0.11, 0.33, 0.11), Y2_uci = c(0.19, 0.88, 0.83, 0.64, 0.88, 0.25, 0.19, 0.19, 0.44, 0.19))) demo.melt <- melt(demo, id.vars=c("ID", "X"), value.name="value", variable.name="var") 的实例具有连接池并默认保持持久连接,这使Dart VM保持活动状态。请查阅问题页面以了解可能的解决方案。

1 个答案:

答案 0 :(得分:2)

这可能是由await之前的response.transform引起的。

您可能需要类似

的内容
  return response.transform(UTF8.decoder).join('');

暂停与makeRequest()无关。 Dart VM似乎在它退出之前等待一些东西。在exit(0);中添加main()作为最后一行会立即退出应用程序。

<强>更新

根据Dart SDK issue

的回复
  

这是由具有连接池的HttpClient实例引起的   这可以让Dart VM保持活力。有两种方法可以避免这种情况:

     

1)明确关闭HttpClient   2)使用非持久连接

import 'dart:async';
import 'dart:convert' show UTF8;
import 'dart:io';

Future main() async {
  await makeRequest();
  print('end of main');
}

Future makeRequest() async {
  var client = new HttpClient();
  var request = await client.postUrl(Uri.parse('https://example.com'));
  var response = await request.close();
  var contents = await response.transform(UTF8.decoder).join();
  print(contents);
  client.close();  // Close the client.
}
import 'dart:async';
import 'dart:convert' show UTF8;
import 'dart:io';

Future main() async {
  await makeRequest();
  print('end of main');
}

Future makeRequest() async {
  var request = await new HttpClient().postUrl(Uri.parse('https://example.com'));
  request.persistentConnection = false;  // Use non-persistent connection.
  var response = await request.close();
  var contents = await response.transform(UTF8.decoder).join();
  print(contents);
}