Dart中Future.value与Future.microtask的差异及执行顺序解析
Dart中Future.value与Future.microtask的行为差异解析
先看两个测试案例及输出:
Case 1
Future.microtask(() => 1).then(print); Future.microtask(() => Future(() => 2)).then(print); Future.value(3).then(print); Future.value(Future(() => 4)).then(print);
输出:
1 3 4 2
Case 2(调换语句顺序)
Future.value(3).then(print); Future.value(Future(() => 4)).then(print); Future.microtask(() => 1).then(print); Future.microtask(() => Future(() => 2)).then(print);
输出:
3 1 4 2
针对这两个案例,下面逐一解答问题:
1. Future.value与Future.microtask的区别是什么?
- Future.value:
- 如果传入非Future类型的值,会立即将该值作为Future的完成结果,同时把后续的
then回调加入微任务队列等待执行。 - 如果传入的是Future对象,则会等待这个传入的Future完成,之后再将
then回调放入对应队列(取决于传入的Future完成时所在的队列)。
- 如果传入非Future类型的值,会立即将该值作为Future的完成结果,同时把后续的
- Future.microtask:
- 会把传入的回调函数直接加入微任务队列,等微任务队列被处理时执行该回调。
- 回调的返回值会作为这个Future的结果;如果回调返回的是Future对象,当前Future会等待这个返回的Future完成,再触发后续的
then回调。
2. 两者谁的优先级更高,谁会先完成?
Dart的任务队列分为微任务队列(优先级更高)和事件队列(优先级更低),只有微任务队列的所有任务处理完毕后,才会处理事件队列的任务。
Future.value(传入非Future值)和Future.microtask的任务都属于微任务队列,优先级完全相同,执行顺序只取决于被加入微任务队列的先后:
- Case1中先调用
Future.microtask(() => 1),再调用Future.value(3),所以先输出1,再输出3。 - Case2中先调用
Future.value(3),再调用Future.microtask(() => 1),所以先输出3,再输出1。
3. 为何最终输出中4和2的顺序始终保持不变?
拆解两者的执行逻辑:
- 输出4的逻辑:
Future.value(Future(() => 4))里的Future(() => 4)是普通Future,它的回调会被直接加入事件队列。当这个事件任务执行完毕后,才会触发外层Future.value的then(print)输出4。 - 输出2的逻辑:
Future.microtask(() => Future(() => 2))会先把回调加入微任务队列;等微任务处理到这个回调时,才会创建Future(() => 2)并将其回调加入事件队列。当这个事件任务执行完毕后,才会触发外层Future.microtask的then(print)输出2。
不管案例中语句顺序如何调换:
Future(() => 4)总是比Future(() => 2)更早进入事件队列:Case1中前者会立即创建事件任务,后者要等微任务执行时才创建;Case2中前者先被调用,更早创建事件任务。- 事件队列按任务加入顺序执行,所以
Future(() => 4)的任务总是先完成,输出4,之后才是Future(() => 2)的任务完成输出2,因此两者顺序始终不变。
内容的提问来源于stack exchange,提问作者Anonymous
相关产品推荐
相关产品推荐

