请教各位大佬,Flutter/dart 中,async 返回的 Future 来源问题,以及什么时候会把 await 后面的代码抛到事件循环里(flutter相关)
这是一段测试代码,很多教程里都有
main() {
print("Main 开始");
A();
print("Main 结束");
}
Future<void> A() async {
print(“A 开始执行这个方法~”);
print(await B());
// print(B());
print(“A 执行结束”);
}
Future<String> B() async {
print(“B 开始执行这个方法~”);
final result = await Future.delayed(Duration(seconds: 3), () => “123”);
// final result = await “123”;
print(“B 执行结束~”);
return Future(() => “请求到的数据:” + result.toString());
}
运行结果:
Main 开始
A 开始执行这个方法~
B 开始执行这个方法~
Main 结束
B 执行结束~
请求到的数据:123
A 执行结束
问下各位大佬:
-
如果一个函数被 async 标记,但内部没有 await ,那么函数内部代码会貌似会同步执行,最后会返回 Future ,这个 Future 是怎么来的?
-
在 A 函数中不使用 await 调用 B 函数(A 函数的注释行),在遇到 B 函数的 Future.delay 时直接返回了 Future 对象给 A ,这个返回给 A 的 Future 具体是怎么来的?
-
通过执行结果,并不是所有遇到 await 函数就把当前函数的后半部分抛到 event_looper 里,因为 await 调用 B 函数后,还是会同步调用 B 函数第一行打印语句。那么究竟是什么情况会导致 await 后面的抛到 event_looper ,是有 Future 对象创建出来的时候么?
-
目前 dart 是可以写 await "123" 代码的,这样写自动变成 await Future.value("123") 么?
请教各位大佬,Flutter/dart 中,async 返回的 Future 来源问题,以及什么时候会把 await 后面的代码抛到事件循环里(flutter相关)
更多关于请教各位大佬,Flutter/dart 中,async 返回的 Future 来源问题,以及什么时候会把 await 后面的代码抛到事件循环里(flutter相关)的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
- JS 的 async 会将返回结果自动包装为 Future ,Dart 也是类似的原理。异步函数会异步执行,返回结果为 Future 类型,跟里面是否使用 await 没什么关系。
你所认为的同步,其实只是因为你这测试用例过于简单,只有 A,B ,给你带来的错觉。
2. 你为什么会认为“遇到 B 函数的 Future.delay 时直接返回了 Future 对象给 A”,你用打印下结果就知道不是你想得那样:
//修改 A 函数的 print(B());为:
var result = B();
result.then((value) => print(value));
3. await 有两个作用:1. 让“await doSomething()”的 doSomething()异步执行( JS,DART 就是“抛事件循环”,其它语言可能就是多线程、协程等) 2. 等待 doSomething()对应的异步任务执行完成,然后再执行剩余部分。所以只有 B 执行完后,才返回执行 A 的后半部分,也就是你说的“同步调用 B 函数第一行打印语句”。
“抛事件循环”,是一种抽象化的模型,容易让人理解得云里雾里。沿用这种模型来说明,应该是先抛 B()到事件循环,再抛 A 的剩余部分到事件循环。
事实上,当 JS 和 Dart 的代码混合了异步逻辑,很难只用事件模型来描述代码的执行情况。比如,假设 B()函数里面await C()
,那 C()是不是就抛到 A 的剩余部分后面了,岂不是 A 的剩余部分还先于 C()执行。当然,你可以再给这个模型补充很多细节,问题是这些细节就牵涉到具体的实现,比如 chrome,mozilla,quickjs 等完全可以采用不同的底层实现。
这并不是说事件模型是错误的,只是说当存在异步逻辑时,事件模型需要补充很多细节,不然就会像你一样陷入混乱,此时可以不用事件模型来理解程序的执行。
4. 不了解,我这里 IDE 提示:“可以去掉 await ,且 await 无效”。无论是还是不是,这种代码没有啥实际价值。
更多关于请教各位大佬,Flutter/dart 中,async 返回的 Future 来源问题,以及什么时候会把 await 后面的代码抛到事件循环里(flutter相关)的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
补充:
1. “函数内部代码会貌似会同步执行”,我理解了,你指的内部代码会作为一个整体被执行,这是正确的。返回 Future 是语法层面的规定,表示这个异步函数的异步执行情况。正如我上面所说的,返回结果会自动包装为 Future ,比如 B 函数,熟练以后是这样:dart<br>//省略上面内容<br>return "请求到的数据:" + result.toString();<br>
在Flutter/Dart中,关于async返回的Future来源及await后代码的处理机制,以下是我的专业解答:
首先,async关键字用于标记一个函数为异步函数,该函数在执行过程中可能会进行耗时操作(如网络请求)。这些异步操作不会立即完成,因此async函数会返回一个Future对象,该对象代表了一个可能在未来某个时间点完成的结果。这个Future对象是由Dart运行时自动创建的,用于封装异步操作的结果。
其次,当在async函数内部使用await关键字时,它会暂停当前异步函数的执行,直到等待的Future对象完成。在这个过程中,await后面的代码实际上并没有被“抛到事件循环里”,而是被挂起等待Future的完成。一旦Future完成,await后面的代码才会继续执行。
在Flutter的事件循环机制中,Future对象及其回调函数的处理遵循Dart的异步模型。Future对象会被添加到事件队列中,等待Dart的事件循环调度执行。当事件循环处理到该Future对象时,会触发其相关的回调函数(如then或catchError中注册的回调),从而继续执行await后面的代码。
综上所述,async返回的Future由Dart运行时创建,而await后的代码在Future完成时继续执行,这一过程由Flutter/Dart的事件循环机制管理。