DART提供了一个FutureOr级的课程,允许写:

FutureOr<int> future;

future = 42; // valid
future = Future.value(42); // also valid

我假设如果可以同步读取值,那么FutureOr将有助于消除事件循环造成的不必要延迟.

但情况似乎并非如此,正如以下所示:

import 'dart:async';

void main() async {
  print('START');
  futureOrExample();
  print('END');
}

void futureOrExample() async {
  FutureOr<int> futureOr = 42;
  print('before await');
  await futureOr;
  print('end await');
}

其中打印:

START
before await
END
end await

当我期待:

START
before await
end await
END

在这种情况下,为什么FutureOr(或者更一般的await 42)是这样工作的呢?

同样,在这种情况下,FutureOr的作用是什么,因为它产生的结果与Future相同?

我知道我可以用SynchronousFuture来达到预期的效果,但我只是想知道FutureOr有什么用.

推荐答案

与DART 2中引入的一样,使用FutureOr是为了方便起见,允许您在现有DART 1 API允许相同内容的情况下提供值或future 值,但只能以可以静态键入的方式提供.

典型的例子是Future.then.Future<T>的签名是Future<R> then<R>(FutureOr<R> action(T value), {Function onError}).

这个 idea 是,你可以对future 的价值采取同步或异步的行动.最初有一个接受同步回调的then函数和一个接受异步回调的chain函数,但这非常烦人,在良好的Dart 1风格中,API被简化为一个接受返回dynamic的函数的then方法,然后判断它是否是future 的.

在DART 1中,很容易允许您返回值或future .DART 2则没有那么宽松,因此引入了FutureOr类型,以允许现有的API继续工作.如果我们从头开始编写API,我们可能会做一些其他的事情,但是将现有的异步代码库迁移到完全不同的地方是不可行的,因此引入了FutureOr类型作为类型级技巧.

FutureOr出现之前很久,await操作最初也被定义为在任何对象上工作.为了一致性和较小的代码,其中e求值为非future 的await e将在future 包装该值并等待该值.这意味着对一个值只有一次快速且可重用的判断(如果不包装它,它是不是将来的),然后剩下的代码是相同的.只有一个代码路径. 如果await在非Future值上同步工作,则必须有一条通过await的同步代码路径,以及一条等待将来的异步路径.这可能会使代码大小翻一番,例如在编译为JavaScript时(或者更糟糕的是,如果同一控制流中有更多的await,您可能会因为一个简单的实现而得到指数级的崩溃).即使您只是通过同步调用延续函数来避免这一点,一些读者也可能会对awaitnot引入异步间隙感到困惑.周围的一个错误可能会导致比赛条件或事情以错误的顺序发生.

因此,最初的设计,早在FutureOr年前,就是让所有await个操作实际上都等待.

FutureOr的引入并没有改变这一推理,即使改变了,现在也将是一个突破性的改变,即在人们期望他们的代码实际给出时间让其他微任务运行的地方等待not个.

Dart相关问答推荐

为什么 Dart 程序在使用词法作用域时会根据声明变量的位置而表现不同?

如何扩展 Dart 套接字 BroadcastStream 缓冲区大小为 1024 字节?

Flutter Drawer 作为单独的小部件不允许修改宽度

Dart中有没有类似python 字典(dictionary) struct ?

Flutter:Firebase FieldValue.serverTimestamp() 到 DateTime 对象

如何在 Dart 中获取数字的长度?

如何将 Stream 转换为 List

Flutter列表视图底部溢出

如何实现从左侧滑动的侧边菜单?

如何正确管理 Flutter 应用中的全局 textScaleFactor?

在 Flutter 的 TextFormField 中管理事件

GestureDetector onTap 卡

Dart 构造函数与静态方法;例如,为什么 int.parse() 不是工厂构造函数?

如何从列表中的元素创建逗号分隔的字符串

有可用的 Dart VM 吗?

如何在 timeLimit 之后使future 的计算超时?

Dart 中的 final 修饰符有什么作用?

Dart 中的抽象基类

将多张map合并/合并为一张map

Dart,如何在你自己的函数中创建一个返回的future ?