来源:未知 时间:2023-05-09 09:16 作者:小飞侠 阅读:次
[导读] Dart异步编程: future, async, await 原文地址: https://dart.cn/codelabs/async-await 这个codelab(代码实验室)教你如何写异步代码使用future和 async 和 await 关键字。使用嵌入式的DartPad编辑器,您可以通...
Dart异步编程: future, async, await原文地址:https://dart.cn/codelabs/async-await 这个codelab(代码实验室)教你如何写异步代码使用future和async 和 await关键字。使用嵌入式的DartPad编辑器,您可以通过运行示例代码和完成练习来测试您的知识。 为了充分利用此代码实验室,您应该具备以下条件:
该代码实验室涵盖了以下内容:
完成此代码实验室的估计时间:40-60分钟。 异步代码的重要性异步操作让您的程序在等待另一个操作完成的同时完成其它工作。下面是一些常见的异步操作:
要在Dart中执行异步操作,您可以使用Future类以及async和await关键字。 示例:错误地使用异步函数以下示例显示了使用异步函数(getUserOrder())的错误方法。 稍后,您将使用async和await修复示例。 在运行此示例之前,请尝试找出问题所在–您认为输出将是什么? // This example shows how *not* to write asynchronous Dart code.String createOrderMessage () { var order = getUserOrder(); return 'Your order is: $order';}Future<String> getUserOrder() { // Imagine that this function is more complex and slow return Future.delayed(Duration(seconds: 4), () => 'Large Latte');}void main () { print(createOrderMessage());} 下面是为什么这个例子不能打印getUserOrder()最终产生的值:
在接下来的部分中,您将学习有关futures,async, 和 await的知识,以便您能够编写使getUserOrder()打印所需值(“Large Latte”)到控制台的必要代码 。
什么是future?future(小写的“ f”)是Future(大写的“ F”)类的实例。 future表示异步操作的结果,并且可以具有两种状态:未完成或已完成。
Uncompleted(未完成)当你调用一个异步函数时,它会返回一个未完成的future。这个future是等待函数的异步操作完成或抛出一个错误。 Completed(完成)如果异步操作成功,则future将使用一个值完成。否则就会出现错误。 Completing with a value(用一个值完成)类型为Future<T>的future以类型为T的值完成。 例如,类型为Future<String>的future会产生一个字符串值。 如果future未产生可用的值,则future的类型为Future<void>。 Completing with an error(带错误完成)如果该函数执行的异步操作由于某种原因失败,则future将以错误完成。 示例:介绍future在下面的示例中,getUserOrder()返回打印到控制台后完成的Future。 由于getUserOrder()不会返回可用的值,因此其类型为Future<void>。 在运行示例之前,请尝试预测将首先打印的内容:“Large Latte” 或者 “Fetching user order…”。 Future<void> getUserOrder() { // Imagine that this function is fetching user info from another service or database return Future.delayed(Duration(seconds: 3), () => print('Large Latte'));}void main() { getUserOrder(); print('Fetching user order...');} 在前面的示例中,即使getUserOrder()在第8行的print()调用之前执行,控制台也会在getUserOrder()的输出(“Large Latte”)之前显示第8行的输出(“Fetching user order…”)。 这是因为getUserOrder()在打印“Large Latte”之前会延迟。 示例:完成时出现错误运行下面的示例,查看future如何在出现错误时完成。稍后您将学习如何处理该错误。 Future<void> getUserOrder() {// Imagine that this function is fetching user info but encounters a bug return Future.delayed(Duration(seconds: 3), () => throw Exception('Logout failed: user ID is invalid'));}void main() { getUserOrder(); print('Fetching user order...');} 在本例中,getUserOrder()结束时将出现一个错误,指示用户ID无效。 您已经了解了futures以及它们是如何完成的,但是如何使用异步函数的结果呢?在下一节中,您将学习如何使用async和await关键字获得结果。
使用futures:async 并 awaitasync和await关键字提供了一种声明性的方式来定义异步函数并使用它们的结果。 使用async和await时,请记住以下两个基本准则:
下面是一个将main()从同步函数转换为异步函数的示例。 首先,在函数体前添加async关键字: main() async {
如果函数具有声明的返回类型,则将类型更新为Future<T>,其中T是函数返回值的类型。 如果该函数未明确返回值,则返回类型为Future<void>: Future<void> main() async { 现在你有一个async函数,你可以使用await关键字等待future完成: print(await createOrderMessage()); 如以下两个示例所示,async和await关键字生成的异步代码看起来非常类似于同步代码。 示例:同步函数// SynchronousString createOrderMessage() { var order = getUserOrder(); return 'Your order is: $order';}Future<String> getUserOrder() { // Imagine that this function is // more complex and slow. return Future.delayed( Duration(seconds: 4), () => 'Large Latte');}// Synchronousmain() { print('Fetching user order...'); print(createOrderMessage());}// 'Fetching user order...'// 'Your order is: Instance of _Future<String>' 示例:异步函数// AsynchronousFuture<String> createOrderMessage() async { var order = await getUserOrder(); return 'Your order is: $order';}Future<String> getUserOrder() { // Imagine that this function is // more complex and slow. return Future.delayed( Duration(seconds: 4), () => 'Large Latte');}// Asynchronousmain() async { print('Fetching user order...'); print(await createOrderMessage());}// 'Fetching user order...'// 'Your order is: Large Latte' 异步的例子在三个方面有所不同:
具有异步和等待的执行流一个async函数会同步运行直到第一个await关键字。这意味着在一个async函数体中,在第一个await关键字之前的所有同步代码都会立即执行。
示例:在异步函数中执行运行下面的示例,看看在async函数体中执行是如何进行的。你认为输出会是什么? void printOrderMessage () async { print('Awaiting user order...'); var order = await getUserOrder(); print('Your order is: $order');}Future<String> getUserOrder() { // Imagine that this function is more complex and slow. return Future.delayed(Duration(seconds: 4), () => 'Large Latte');}Future<void> main() async { countSeconds(4); await printOrderMessage();}// You can ignore this function - it's here to visualize delay time in this example.void countSeconds(s) { for( var i = 1 ; i <= s; i++ ) { Future.delayed(Duration(seconds: i), () => print(i)); }} 在运行了上述示例中的代码后,尝试颠倒第4行和第5行: var order = await getUserOrder();print('Awaiting user order...'); 注意,输出的时间发生了变化,现在print('Awaiting user order')出现在createOrderMessage()中的第一个await关键字之后。 练习:练习使用async并等待以下练习是一个失败的单元测试,其中包含部分完成的代码段。 您的任务是通过编写代码使测试通过来完成练习。 您无需实现main()。 要模拟异步操作,请调用为您提供的以下函数:
第1部分: reportUserRole()向reportUserRole()函数添加代码,使其执行以下操作:
第2部分: reportLogins()实现async函数reportLogins(),以便执行以下操作:
// Part 1//You can call the provided async function fetchRole to return the user roleFuture<String> reportUserRole() async { // your implementation here}// Part 2// Implement reportLogins here// You can call the provided async function fetchLoginAmount to return the number of times that the user has logged in.reportLogins(){} 参考调用: Future<String> reportUserRole() async { var username = await fetchRole(); return 'User role: $username';}Future<String> reportLogins() async { var logins = await fetchLoginAmount(); return 'Total number of logins: $logins';}
处理错误要处理async函数中的错误,使用try-catch: try { var order = await getUserOrder(); print('Awaiting user order...'); } catch (err) { print('Caught error: $err'); } 在async函数中,您可以像在同步代码中一样编写try-catch子句。 示例:async并使用try-catch进行await运行以下示例以查看如何处理异步函数中的错误。 您认为输出结果是什么? void printOrderMessage () async { try { var order = await getUserOrder(); print('Awaiting user order...'); print(order); } catch (err) { print('Caught error: $err'); }}Future<String> getUserOrder() { // Imagine that this function is more complex. var str = Future.delayed(Duration(seconds: 4), () => throw 'Cannot locate user order'); return str;}Future<void> main() async { await printOrderMessage();} 练习:练习处理错误下面的练习提供了使用前一节中描述的方法处理异步代码错误的实践。为了模拟异步操作,您的代码将调用以下为您提供的函数:
使用async和await来实现一个异步changeUsername()函数,它做以下事情:
Future<String> changeUsername () async { try { return await fetchNewUsername(); } catch (err) { return err.toString(); }} 练习:将所有内容放在一起是时候在最后一个练习中练习你所学到的东西了。为了模拟异步操作,本练习提供了异步函数getUsername()'和logoutUser():
编写以下内容: 第1部分: addHello()
第2部分: greetUser()
第3部分: sayGoodbye()
// Part 1addHello(){}// Part 2//You can call the provided async function fetchUsername to return the usernamegreetUser(){}// Part 3//You can call the provided async function logoutUser to logout the usersayGoodbye(){} 参考实现: String addHello(user) => 'Hello $user';Future<String> greetUser() async { var username = await fetchUsername(); return addHello(username);}Future<String>sayGoodbye() async { try { var result = await logoutUser(); return '$result Thanks, see you next time'; } catch (e) { return 'Failed to logout user: $e'; }} 接下来是什么?恭喜,您已经完成了代码实验室! 如果您想了解更多信息,请参考以下建议:
|
自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习
京ICP备14009008号-1@版权所有www.zixuephp.com
网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com