这是一段测试代码,很多教程里都有
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") 么?
1
CLMan 308 天前
1. 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 无效”。无论是还是不是,这种代码没有啥实际价值。 |