【问题标题】:Reusable Sync HttpClient Request可重用的同步 HttpClient 请求
【发布时间】:2015-08-09 14:57:38
【问题描述】:

我需要一个可重用的函数,它发出 HTTP 请求并等待其完成,然后将响应作为字符串返回。

主要功能如下:

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;
}

我尝试在listen 中使用asyncawait 定义函数,在listen 中返回contents 而没有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.

EDIT2:

提交this issue on GitHub后,我发现HttpClient的实例有一个连接池并且默认保持持久连接,这使得Dart VM保持活跃。请查阅问题页面以了解可能的解决方案。

【问题讨论】:

    标签: dart httprequest dart-async dart-http


    【解决方案1】:

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

    你可能想要类似的东西

      return response.transform(UTF8.decoder).join('');
    

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

    更新

    根据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);
    }
    

    【讨论】:

    • 这和我的第一种情况类似,所以可以,但我想没有其他方法可以做到这一点。
    • 对,我没有仔细研究您的第一个案例,因为它没有引起问题。您可以在第二种情况下使用 Completer,但除了不必要地增加复杂性之外,您并没有真正获得任何好处。
    • 但是,使用他的解决方案,它会打印响应内容,然后打印*** request complete ***,然后在执行终止之前需要几秒钟而不做任何事情。将break 放在for 中可以解决这个问题,但看起来不太好。有谁知道为什么会这样?
    • 插入break; 毫无意义。您能否用您当前的整个代码更新您的问题?
    • 感谢所有帮助!我已经在使用exit(0),就像你说的,这可能是一个错误。我要举报。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多