【问题标题】:Using Dart, how to properly return an HttpResponse using Future's使用 Dart,如何使用 Future 正确返回 HttpResponse
【发布时间】:2014-08-06 03:21:00
【问题描述】:

我正在尝试创建一个非常简单的 http 服务器,它只做一件事。收到 HttpRequest 后,它会在本地数据库服务器上运行一个查询,并根据该查询返回一个字符串。

我正在学习 Dart,但我无法掌握 Futures。我以为我理解它们,但这个例子让我相信我真的不知道它们是如何工作的。所以,我不仅在寻找解决这个问题的方法,而且我也很乐意接受任何建议。

注意:这段代码是我一直在尝试完成的一个非常原始的示例,为了联系 Stackoverflow 社区,我已尽可能缩短/简化它,同时保持问题完好无损。

这是我的 server.dart 代码

import 'dart:io';
import 'package:sqljocky/sqljocky.dart';


final connection = new ConnectionPool(host: 'localhost', port: 3306, user: 'root', password: null, db: 'server1');

main() {

  HttpServer.bind(InternetAddress.ANY_IP_V4, 9090)..then((server) {
    print("serving generic database query on localhost:9090");
    server.listen((request) {
      if (request.method == "GET") {
        request.response.write(getResults());
        request.response.close();
      }
      else {
        request.response.statusCode = HttpStatus.BAD_REQUEST;
      }
    });
  });
}


String getResults() {

  StringBuffer sb = new StringBuffer();
  sb.write("START--");
  connection.query("select name, email, zkey from users")
      ..then((results) {
    results.forEach((row) {
      sb.write(row.toString());
      print(row.toString());
    });
  });

  sb.write("--END");
  print(sb.toString());

  return sb.toString();
}

因此,如果我向该服务器发送请求,它会返回“START----END”。 服务器打印出预期的查询结果,然后打印出“START----END”。 这让我相信我的请求响应正在关闭并在查询结果处理完成之前返回。

所以无论我 curl localhost:9090/asdf 还是实际构建客户端 http 请求发送者,我都没有得到我期望的响应......这是一个数据库查询结果。

提前致谢

【问题讨论】:

    标签: dart dart-io dart-async sqljocky


    【解决方案1】:

    "START----END" 被“乱序”打印是期货的一种行为,一开始大多数开发人员都会感到困惑。
    connection.query() 这样返回未来的调用不会立即执行,而是会被加入队列以供以后执行。当前线程继续执行,直到完成,然后队列一个接一个地被处理。

    在您的代码中不起作用的是您执行异步调用 connection.query() 并继续进行,就好像它是同步调用一样。这在 Dart 中永远行不通。当您开始异步执行时,您无法返回同步。 (据我所知,计划中的 async/await 应该可以解决这个问题)。

    更多详情请访问 dartlang.org The Event Loop and Dart

    编辑测试代码

    import 'dart:io';
    import 'package:sqljocky/sqljocky.dart';
    
    final connection = new ConnectionPool(host: 'localhost', port: 3306, user: 'root', password: null, db: 'server1');
    
    main() {    
      HttpServer.bind(InternetAddress.ANY_IP_V4, 9090)..then((server) {
        print("serving generic database query on localhost:9090");
        server.listen((request) {
          if (request.method == "GET") {
            getResults()
            .then((result) { 
              print('Result: $result'); 
              request.response.write(result);
              request.response.close();
            });
          }
          else {
            request.response.statusCode = HttpStatus.BAD_REQUEST;
          }
        });
      });
    }
    
    Future<String> getResults() { 
    
      StringBuffer sb = new StringBuffer();
      sb.write("START--");
      return connection.query("select name, email, zkey from users") 
      .then((Result results) => results.toList())
      .then((list) {
        list.forEach((row) {
          sb.write(row.toString());
        });
        sb.write("--END");
      })
      .then((_) => sb.toString());
    }
    

    另请参阅 Gregs 对此问题的回答如何阅读 SqlJocky 结果sqljocky querying database synchronously

    【讨论】:

    • 现在我已经用经过测试的代码更新了答案。另一个注意事项:你不应该使用.. 来代替.then,(只有一个点)否则你将所有连续的.then() 调用连接到第一个未来,但你应该始终连接到最后一个返回的未来。
    • 看起来不错。我不知道建立在回报。谢谢@günter-zöchbauer
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-05
    相关资源
    最近更新 更多