Dart语法基础补充

news/2024/11/28 11:35:37/

Asynchrony support

Dart 库中充满了返回 Future 或 Stream 对象的函数。 这些函数是异步的:它们在设置一个可能耗时的操作(例如 I/O)后返回,而不等待该操作完成。

async 和 await 关键字支持异步编程,让编写看起来类似于同步代码的异步代码。

参考:Future class - dart:async library - Dart API

Stream class - dart:async library - Dart API

Handling Futures

需要已完成的 Future 的结果时,有两种选择:

  • 使用异步和等待。
  • 使用 Future API。

使用 async 和 await 的代码是异步的,但它看起来很像同步代码。 例如,下面是一些使用 await 等待异步函数结果的代码:

await lookUpVersion();

 要使用 await,代码必须在异步函数中——标记为异步的函数:

Future<void> checkVersion() async {var version = await lookUpVersion();// Do something with version
}

 注意:虽然异步函数可能会执行耗时的操作,但它不会等待这些操作。 相反,async 函数只会执行到它遇到第一个 await 表达式。 然后它返回一个 Future 对象,仅在 await 表达式完成后才恢复执行。

在使用 await 的代码中使用 try、catch 和 finally 来处理错误和清理:

try {version = await lookUpVersion();
} catch (e) {// React to inability to look up the version
}

 可以在一个异步函数中多次使用 await。 例如,以下代码等待函数结果三次:

var entrypoint = await findEntryPoint();
var exitCode = await runExecutable(entrypoint, args);
await flushThenExit(exitCode);

 在 await 表达式中,表达式的值通常是一个 Future; 如果不是,则该值会自动包装在 Future 中。 此 Future 对象指示返回对象的承诺。 await 表达式的值是返回的对象。 await 表达式使执行暂停,直到该对象可用。

void main() async {checkVersion();print('In main: version is ${await lookUpVersion()}');
}

 注意:前面的示例使用异步函数 (checkVersion()) 而不等待结果——如果代码假定函数已完成执行,这种做法可能会导致问题。 

Declaring async functions

 异步函数是函数体标有 async 修饰符的函数。

将 async 关键字添加到函数使其返回 Future。 例如,考虑这个同步函数,它返回一个字符串:

String lookUpVersion() => '1.0.0';

 把它改成一个异步函数——例如,因为Future的实现会很耗时——返回的值是一个Future:

Future<String> lookUpVersion() async => '1.0.0';

请注意,函数的主体不需要使用 Future API。 如果需要,Dart 会创建 Future 对象。 如果函数没有返回有用的值,请将其返回类型设置为 Future<void>。

Handling Streams

需要从Stream中获取值时,有两种选择:

  • 使用异步和异步 for 循环(等待)。
  • 使用 Stream API。

注意:在使用 await for 之前,请确保它使代码更清晰,并且确实想要等待Stream的所有结果。 例如,通常不应该为 UI 事件侦听器使用 await for,因为 UI 框架会发送无穷无尽的事件流。

异步 for 循环具有以下形式:

await for (varOrType identifier in expression) {// Executes each time the stream emits a value.
}

 expression 的值必须具有 Stream 类型。 执行过程如下:

  • 等到Stream发出一个值。
  • 执行 for 循环的主体,并将变量设置为发出的值。
  • 重复 1 和 2,直到Stream关闭。

要停止收听Stream,可以使用 break 或 return 语句,它会跳出 for 循环并取消订阅流。

如果在实现异步 for 循环时出现编译时错误,请确保 await for 位于异步函数中。 例如,要在应用程序的 main() 函数中使用异步 for 循环,必须将 main() 的主体标记为异步:

void main() async {// ...await for (final request in requestServer) {handleRequest(request);}// ...
}

 异步编程参考:

Library tour | Dart

Generators

需要延迟生成一系列值时,请考虑使用生成器函数。 Dart 内置支持两种生成器函数:

  • 同步生成器:返回一个 Iterable 对象。Iterable class - dart:core library - Dart API
  • 异步生成器:返回一个 Stream 对象。​​​​​​https://api.dart.dev/stable/dart-async/Stream-class.html

实现一个同步生成器函数,将函数体标记为sync*,使用yield语句传递值:

Iterable<int> naturalsTo(int n) sync* {int k = 0;while (k < n) yield k++;
}

 要实现异步生成器函数,将函数体标记为 async*,并使用 yield 语句传递值:

Stream<int> asynchronousNaturalsTo(int n) async* {int k = 0;while (k < n) yield k++;
}

 如果你的生成器是递归的,你可以通过使用 yield* 来提高它的性能:

Iterable<int> naturalsDownFrom(int n) sync* {if (n > 0) {yield n;yield* naturalsDownFrom(n - 1);}
}

 

Callable classes

要允许 Dart 类的实例像函数一样被调用,请实现 call() 方法。

call() 方法允许任何定义它的类来模拟一个函数。 此方法支持与普通函数相同的功能,例如参数和返回类型。

class WannabeFunction {String call(String a, String b, String c) => '$a $b $c!';
}var wf = WannabeFunction();
var out = wf('Hi', 'there,', 'gang');void main() => print(out);Log
Hi there, gang!

 

Isolates

大多数计算机,甚至在移动平台上,都具有多核 CPU。 为了利用所有这些内核,开发人员传统上使用并发运行的共享内存线程。 然而,共享状态并发很容易出错,并可能导致代码复杂化。

所有 Dart 代码都运行在 isolates 中,而不是线程。 每个 Dart isolate 使用单个执行线程并且不与其他 isolate 共享可变对象。 旋转多个隔离创建多个执行线程。 这使得多线程没有其主要缺点,竞争条件。https://en.wikipedia.org/wiki/Race_condition#In_software

  • Concurrency in Dart
  • dart:isolate API reference, including Isolate.spawn() and TransferableTypedData
  • Background parsing cookbook on the Flutter site
  • Isolate sample app

Typedefs

类型别名——通常称为 typedef,因为它是用关键字 typedef 声明的——是一种引用类型的简洁方式。 下面是声明和使用名为 IntList 的类型别名的示例:

typedef IntList = List<int>;
IntList il = [1, 2, 3];

 

类型别名可以有类型参数:

typedef ListMapper<X> = Map<X, List<X>>;
Map<String, List<String>> m1 = {}; // Verbose.
ListMapper<String> m2 = {}; // Same thing but shorter and clearer.

 在大多数情况下,建议对函数使用内联函数类型而不是 typedef。 但是,函数 typedef 仍然有用:

typedef Compare<T> = int Function(T a, T b);int sort(int a, int b) => a - b;void main() {assert(sort is Compare<int>); // True!
}


http://www.ppmy.cn/news/24352.html

相关文章

Fluent Python 笔记 第 8 章 对象引用、可变性和垃圾回收

本章先以一个比喻说明 Python 的变量&#xff1a;变量是标注&#xff0c;而不是盒子。如果你不知道引用式变量是什么&#xff0c;可以像这样对别人解释别名。 然后&#xff0c;本章讨论对象标识、值和别名等概念。随后&#xff0c;本章会揭露元组的一个神奇特性&#xff1a;元…

【Hello Linux】 Linux的权限以及Shell原理

作者&#xff1a;小萌新 专栏&#xff1a;Linux 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;介绍Linux的基础命令 Linux的权限以及Shell原理Shell的运行原理权限Linux中权限的概念如何切换用户如何提升当前操作的权限如何添加信任…

【前端vue2面试题】2023前端最新版vue模块,高频17问(上)

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;博主收集的关于vue2面试题(上) 目录 vue2面试题 1、$route 和 $router的区别 2、一个…

【随笔】我迟到的2022年度总结:突破零粉丝,1个月涨粉1000+,2023年目标3万+

前言 我是21年12月注册的csdn&#xff0c; 作为用户平时看看文章&#xff0c;从未参与过写文章这件事。 但这一年的时间我见证了很多新号的崛起&#xff0c;有的号我平时关注比较多&#xff0c;看着他们从零粉丝突破了三万甚至五万的粉丝量。 在csdn上遇到了我的贵人&#x…

湿敏电阻的原理,结构,分类与应用总结

🏡《总目录》 0,概述 湿敏电阻是指电阻值随着环境的湿度变化而变化的电阻,本文对其工作原理,结构,分类和应用场景进行总结。 1,工作原理 湿敏电阻是利用湿敏材料制成的,湿敏材料吸收空气中水分时,自身的阻值发生变化。 2,结构 如下图所示,市民电阻包括4个部分构成,…

【JavaWeb项目】简单搭建一个前端的博客系统

博客系统项目 本项目主要分成四个页面: 博客列表页博客详情页登录页面博客编辑页 该系统公共的CSS样式 common.css /* 放置一些各个页面都会用到的公共样式 */* {margin: 0;padding: 0;box-sizing: 0; }/* 给整个页面加上背景 */ html, body{height: 100%; }body {backgrou…

【MySQL】 事务

&#x1f60a;&#x1f60a;作者简介&#x1f60a;&#x1f60a; &#xff1a; 大家好&#xff0c;我是南瓜籽&#xff0c;一个在校大二学生&#xff0c;我将会持续分享Java相关知识。 &#x1f389;&#x1f389;个人主页&#x1f389;&#x1f389; &#xff1a; 南瓜籽的主页…

AI推理计算框架中的内存优化

背景 内存管理是AI计算中非常重要的一部分。我们希望模型计算时占用内存尽可能小&#xff0c;这样我们训练或推理时就可以用更大的batch size使其尽快收敛&#xff0c;或者提高吞吐率。又或者让我们可以使用参数更多、或更复杂的模型从而达到更好的准确率。由于现代深度学习模…