7

我使用我的 postgres 数据库查询来确定我的下一步操作。而且我需要等待结果才能执行下一行代码。现在我conn.query返回了一个 Future,但是当我将代码放在另一个函数中时,我无法让它异步。

main() {
  // get the database connection string from the settings.ini in the project root folder 
  db = getdb();
  geturl().then((String url) => print(url));
}

Future geturl() {
  connect(db).then((conn) {
    conn.query("select trim(url) from crawler.crawls where content IS NULL").toList()
      .then((result) { return result[0].toString(); })
      .catchError((err) => print('Query error: $err'))
      .whenComplete(() {
        conn.close();
      });
  });
}

我只想geturl()等待返回值,但无论我做什么;它立即开火。谁能给我指出一个解释我在这里缺少什么的文档?

4

4 回答 4

10

您目前实际上并没有返回 Future geturl。您必须实际返回您使用的期货:

Future geturl() {
  return connect(db).then((conn) {
    return conn.query("select trim(url) from crawler.crawls where content IS NULL").toList()
      .then((result) { return result[0].toString(); })
      .catchError((err) => print('Query error: $err'))
      .whenComplete(() {
        conn.close();
      });
  });
}
于 2014-11-10T16:57:07.617 回答
7

为了详细说明 John 的评论,以下是您如何使用 async/await 来实现它。(在 Dart 1.9 中添加了 async/await 功能)

main() async {
  try {
    var url = await getUrl();
    print(url);
  } on Exception catch (ex) {
    print('Query error: $ex');
  }
}

Future getUrl() async {
  // get the database connection string from the settings.ini in the project root folder 
  db = getdb();
  var conn = await connect(db);
  try {      
    var sql = "select trim(url) from crawler.crawls where content IS NULL";
    var result = await conn.query(sql).toList();
    return result[0].toString();
  } finally {
     conn.close();
  }
}
于 2014-11-16T22:09:18.567 回答
4

我更喜欢在具有多链期货的场景中(希望很快就会成为过去await),使用 Completer。它是这样工作的:

 Future geturl() {
   final c = new Completer();  // declare a completer.

   connect(db).then((conn) {
     conn.query("select trim(url) from crawler.crawls where content IS NULL").toList()
       .then((result) { 
           c.complete(result[0].toString()); // use the completer to return the result instead
        })
       .catchError((err) => print('Query error: $err'))
       .whenComplete(() {
         conn.close();
       });
   });

   return c.future;  // return the future to the completer instead
 }
于 2014-11-10T17:23:53.737 回答
3

要回答您的“文档在哪里”的问题:https ://www.dartlang.org/docs/tutorials/futures/

你说你试图让你的geturl()函数“等待返回值”。返回 Future 的函数(如上一个答案中的示例)将立即执行并返回,它不会等待。事实上,这正是 Futures 的用途,以避免代码在等待数据到达或外部进程完成时什么都不做或“阻塞”。

要理解的关键是,当解释器then()在 Future 上调用或 'catchError()' 时,它不会执行里面的代码,而是将其放在一边,以便稍后在 future '完成'时执行,然后只是继续执行以下任何代码。

换句话说,在 Dart 中使用 Futures 时,您正在设置将非线性执行的代码块。

于 2014-11-11T01:52:15.453 回答