2014-11-10 3 views
1

Я использую свой запрос базы данных postgres для определения моего следующего действия. И мне нужно дождаться результатов, прежде чем я смогу выполнить следующую строку кода. Теперь мой conn.query возвращает Будущее, но я не могу получить его async, когда я помещаю свой код в другую функцию.Ждите, когда закончится будущее

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() ждать возвращаемого значения, но все, что я делаю; он срабатывает немедленно. Может ли кто-нибудь указать мне часть документов, которая объясняет, что мне здесь не хватает?

ответ

6

В настоящее время вы не возвращаете Будущее в 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(); 
     }); 
    }); 
} 
2

Я предпочитаю, в сценариях с несколькими цепью фьючерсов (надеюсь, скоро ушли в прошлое раз 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 
} 
1

Чтобы ответить на ваши «где Документах» вопрос: https://www.dartlang.org/docs/tutorials/futures/

Вы сказали, что вы пытаетесь получить geturl() функцию "ждать возвращаемого значения. Функция, возвращающая будущее (как в примере в предыдущем ответе), будет выполняться и немедленно возвращаться, она не будет ждать. На самом деле это именно то, для чего нужны фьючерсы, чтобы избежать кода, ничего не делающего или «блокирующего», ожидая прибытия данных или завершения внешнего процесса.

Главное, чтобы понять, что, когда интерпретатор получает вызов then() или «catchError()» в будущем, он не выполняет код внутри, он откладывает его в сторону, чтобы выполнить позже, завершает ", а затем просто сохраняет права на выполнение любого следующего кода.

Другими словами, при использовании Futures in Dart вы создаете куски кода, которые будут выполняться нелинейно.

+0

Да, я прочитал, что часть документации, но я предполагаю, что я просто не получить ту часть, где я прохожу будущее через функцию. Теперь имеет смысл передать – Dani

5

Чтобы подробно описать комментарий Джона, вы можете реализовать это с помощью async/wait. (Асинхронный/Await функция была добавлена ​​в Dart 1.9)

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(); 
    } 
} 
Смежные вопросы