Dart:未来值与未来微任务之间的差异

ktecyv1j  于 2023-01-18  发布在  其他
关注(0)|答案(1)|浏览(148)

Future.valueFuture.microtask之间有何区别
案例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

案例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.valueFuture.microtask有什么区别?
    1.哪一个更优先?Future.value还是Future.microtask先完成?
    1.为什么最终输出(42)的顺序保持不变?
    有人能解释一下事件和微任务队列的这种行为吗?
ryevplcw

ryevplcw1#

Future.microtask调度一个微任务来执行参数函数,然后用该函数调用的结果来完成将来的任务。
Future()Future.delayed调度一个定时器任务,前者与Duration.zero一起执行一个函数,并利用该函数调用的结果完成将来的任务。
Future.value接受一个 * value *,而不是一个函数来调用。如果你使用Future.value(computation()),计算会立即执行(或者至少是 * started *,如果是异步的话)。
如果执行Future.microtask(computation),计算将在后面的微任务中 * 启动 *。
在每种情况下,如果函数返回一个future,或者传递给Future.value的值是一个future,那么在Future构造函数返回的future以相同的结果完成之前,您还必须等待future完成。
举个具体的例子:

Future.value(3).then(print);

这将创建一个future,其值为3,但是,由于future * 承诺 * 不会在调用then时立即调用回调,如then(print),因此它会调度一个微任务,以便在以后的某个时间实际调用print回调,因此,您会得到额外的延迟。
更详细地说:

Future.microtask(() => 1).then(print); 
  // This `Future.microtask(...)` creates future, call it F1, 
  // and schedules a microtask M1 to call `() => 1` later.
  // Then adds callback C1 (`then(print)`) to F1, but F1 isn't completed yet, 
  // so nothing further happens.

  Future.microtask(() => Future(() => 2)).then(print); 
  // Creates future F2 (`Future.microtask(...)`), 
  // schedules microtask M2 to run `() => Future(() => 2)` later, 
  // then callback C2 (`.then(print)`) to F2.

  Future.value(3).then(print); 
  // Creates future F3 with value 3. Adds C3 (`then(print)`) to F3.
  // Since F3 is complete, it schedules M3 to invoke C3.

  Future.value(Future(() => 4)).then(print);
  // Creates future F4 (`Future(() => 4)`) 
  // which starts *timer* T1 with duration zero to run `() => 4`.
  // Then creates future F5 (`Future.value(...)`) with "value" F4.
  // Completing with a future adds a callback C4 to F4, 
  // to notify F5 when a result is ready.
  // Then adds callback C5 (`then(print)`) to F5.

这是立即发生的事情,然后事件/微任务循环接管。

  • 最后M1运行,它执行() => 1到值1。
  • 然后F1以值1结束。
  • 然后,F1通知其所有现有回调,后者用1调用C1。
  • 其打印"1"。
  • 然后运行M2,计算Future(() => 2)
  • 这创建了未来F6(Future(...))和持续时间为零的计时器T2。
  • 然后用未来的F6完成F2,
  • 这意味着向F6添加回调C6以通知F2结果。
  • 然后M3运行,调用值为3的C3。
  • 打印"3"。
  • 现在所有微任务都完成了。
  • 计时器T1运行,将() => 4评估为4。
  • F4以值4结束。
  • F4调用其现有回调,C4调用4。
  • 这样就完成了值为4的F5,
  • 并且用值4调用其现有的回调C5。
  • 打印"4"。
  • 定时器T2运行() => 2,并以值2完成F6。
  • 这将使用值2运行F6的现有回调C6。
  • 该回调函数以值2结束F2,
  • 并且它使用值2调用F2的现有回调C2
  • 打印"2"。

因此,三个微任务、两个计时器和一些未来的结果传播之后,您将得到所看到的结果。
第二个例子可以用同样的方法完成:

Future.value(3).then(print);
  // Schedule a microtask to print 3.
  Future.value(Future(() => 4)).then(print);
  // Schedule a timer to (going through an extra future) print 4.
  Future.microtask(() => 1).then(print);
  // Schedule a microtask to compute and print 1.
  Future.microtask(() => Future(() => 2)).then(print);
  // Schedule a microtask to schedule a timer to eventually print 2.

只有微任务的3和1应该按顺序先打印,然后打印4,再打印2,因为2-timer被安排在4-timer之后。3 - 1 - 4 - 2,这就是你看到的。

相关问题