【问题标题】:Dart HTTP server and FuturesDart HTTP 服务器和期货
【发布时间】:2014-08-06 07:58:49
【问题描述】:

我正在尝试编写简单的 HTTP 服务器来解析 client.getUrl() 的结果。除了我无法写回 http 请求对象(打印到控制台工作正常)之外,我已经完成了所有工作。

相关代码为:

main() {
  HttpServer.bind(InternetAddress.ANY_IP_V4, 4040)
      .then((HttpServer server) {
    print('listening on localhost, port ${server.port}');
    server.listen((HttpRequest request) {
      Future loadedContent = loadUrl(furl);
      loadedContent.then((content) => print(content));
  //  loadedContent.then((content) => request.response.write(content));

      request.response.close();
      print ("response closed");
    });
  }).catchError((e) => print(e.toString()));
}

问题是主要功能在我从 Future 获得结果之前结束(通过打印出现在结果之前的第二个“响应关闭”来解决这个问题)。有没有办法在主函数中等待结果?

编辑:它与Dart HttpRequest return future有关 我会重写我的代码,但是如果有办法在 main 函数中等待 getUrl Future,我会更喜欢它。

编辑:我的 loadUrl

Future loadUrl(String url)
{
  final c = new Completer();
  HttpClient client = new HttpClient();
  client.addCredentials(
          Uri.parse("https://*****.tpondemand.com/api"),
          "tprealm",
          new HttpClientBasicCredentials("*****", "*****"));
  client.getUrl(Uri.parse(url))
      .then((HttpClientRequest request) {
        // Optionally set up headers...
        // Optionally write to the request object...
        // Then call close.

        return request.close();
      })
      .then((HttpClientResponse response) {
        // Process the response.
        //print(response.reasonPhrase);
        response.transform(UTF8.decoder).listen((contents) {
             // handle data
            Map parsedMap = JSON.decode(contents);
            c.complete(parsedMap);
            //req.response.write(parsedMap["Items"][0]);
           });

      });
  return c.future;
  }

最后一次编辑:这是工作代码

import 'dart:io';
import 'dart:async';
import 'package:http_server/http_server.dart';
import 'dart:convert';

final furl = "https://***.tpondemand.com";

Future loadUrlBody(String url) {
  final c = new Completer(); 
  HttpClient client = new HttpClient();
  client.addCredentials(Uri.parse("https://***.tpondemand.com/api"), "tprealm", new HttpClientBasicCredentials("user", "password"));
  client.getUrl(Uri.parse(url))
      .then((HttpClientRequest response) => response.close())
      .then(HttpBodyHandler.processResponse)
      .then((HttpClientResponseBody body) {
       c.complete(body);
      });
  return c.future;
}
main() {
  final filter = "/api/v1/Userstories?format=json&where=(Team.Id+eq+111111)&include=[Name,CreateDate,ModifyDate,LastCommentDate]&take=1000";
  HttpServer.bind(InternetAddress.ANY_IP_V4, 4040).then((HttpServer server) {
    print('listening on localhost, port ${server.port}');
    server.listen((HttpRequest request) {
      print(request.connectionInfo.remoteAddress);
      loadUrlBody(furl + filter).then((content) {
        Map parsedMap = content.body;
        //print("Map parsed");
        request.response.write(parsedMap["Items"]);
        request.response.close();
        //print("response closed");
      }).catchError((e) => print(e.toString()));
    });
  }).catchError((e) => print(e.toString()));
}

【问题讨论】:

  • 如果loadUrl 没有返回Future,请将loadUrl 的来源添加到您的问题中。
  • 我更新了我的答案。如果您使用基于链接问题中显示的getData() 方法的loadUrl() 方法,则只需稍作改动即可。
  • 很遗憾地告诉你,等待响应不是飞镖的方式,对于所有异步语言都是如此。
  • 啊,不,我想避免这种方式。现在我可能对动态类型有一些问题。我的 loadUrl 看起来应该如何以及它应该返回什么?我会用我当前的版本更新我的问题。

标签: dart dart-io dart-async


【解决方案1】:

当您的 loadUrl() 返回一个 Future(它可能应该)时,这应该可以工作

main() {
  HttpServer.bind(InternetAddress.ANY_IP_V4, 4040)
      .then((HttpServer server) {
    print('listening on localhost, port ${server.port}');
    server.listen((HttpRequest request) {
      loadUrl(furl).then(() {
        // loadedContent.then((content) => print(content));
        loadedContent.then((content) => request.response.write(content));

        request.response.close();
        print ("response closed");
      });
    });
  }).catchError((e) => print(e.toString()));
} 

更新

你需要修改你的getData()loadUrl()方法

Future getData(HttpRequest request) { // added return type 'Future' (not necessary)
  return dao.findAll().then((value) { // added 'return'
    print(value);
  });
}

更新 2

Future loadUrl(String url)
{
  // final c = new Completer(); // <== commented out
  HttpClient client = new HttpClient();
  client.addCredentials(
          Uri.parse("https://*****.tpondemand.com/api"),
          "tprealm",
          new HttpClientBasicCredentials("*****", "*****"));
  return client.getUrl(Uri.parse(url))                      // <== added return
      .then((HttpClientRequest request) {
        // Optionally set up headers...
        // Optionally write to the request object...
        // Then call close.

        return request.close();
      })
      .then((HttpClientResponse response) {
        // Process the response.
        //print(response.reasonPhrase);
        return response.transform(UTF8.decoder).listen((contents) { // <== added return
             // handle data
            Map parsedMap = JSON.decode(contents);
            // c.complete(parsedMap); // <== commented out
            //req.response.write(parsedMap["Items"][0]);
           }).asFuture();  // <== added `.asFuture()`

      });
   // return c.future; // <== commented out
}

通常,在每次调用返回 Future 的方法之前添加 return 就足够了,那么您可以避免使用完成程序。 Completer 仅适用于更复杂的情况(例如,当您从一种方法返回 completer.future 但从其他地方完成它时,例如事件处理程序)。

【讨论】:

  • 如果可能,请将代码添加到您的问题中(不在评论中)
  • 很好,loadUrl 似乎工作正常。 main 中存在问题,loadedContent 现在不存在。我通过将行更改为: loadUrl(furl).then((content) { // loadedContent.then((content) => print(content)); request.response.write(content); 似乎很接近,因为它现在可以工作了,只是它返回一个 '_SinkTransformerStreamSubscription' 的实例
  • 我添加了.asFuture();。如果这不起作用,您可以使用您已经拥有的 Completer 解决方案。
  • 很好,仍然无法正常工作,但你帮我解决了主要问题,非常感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-29
  • 2019-08-09
  • 1970-01-01
  • 2020-05-09
  • 2020-01-30
  • 2020-10-17
  • 2021-05-09
相关资源
最近更新 更多