简体   繁体   English

Dart 事件队列和微任务

[英]Dart event queue and microtask

i am trying to understand, how dart event loop works.我想了解 dart 事件循环是如何工作的。 I read the event loop article from the website The Event Loop and Dart and the author explain pretty good how event loop in dart works.我从The Event Loop and Dart网站上阅读了事件循环文章,作者很好地解释了 dart 中的事件循环是如何工作的。

But what i don't understand is, how event get queue.但我不明白的是,事件如何排队。 For example例如

new Future(() => 21)
    .then((v) => v*2)
    .then((v) => print(v));

Will here dart gonna create three entries in the event queue or just one?这里 dart 会在事件队列中创建三个条目还是一个? I know, that the class Future is responsible for delay execution and when i create an object from it like我知道,类 Future 负责延迟执行,当我从它创建一个对象时

new Future(() => 21)

it will be just one entry in the event loop.它只是事件循环中的一个条目。

In this article, that i have mentioned above, i read about microtask.在我上面提到的这篇文章中,我阅读了微任务。 This microtask is going to execute before event queue, but i don't see any sense, why dart team implement this microtask?这个微任务将在事件队列之前执行,但我看不出任何意义,为什么 dart 团队实施这个微任务? Maybe i need some example!也许我需要一些例子!

After some investigation it appears that the right answer is "they will be executed in the next event loop"经过一番调查,似乎正确的答案是“它们将在下一个事件循环中执行”

To test it you can write something like this:要测试它,您可以编写如下内容:

import "dart:async";
void main() {
  new Future(() {
    scheduleMicrotask(()=>print("before loop 1"));
    print("in event loop");
  }).then((_) {
    scheduleMicrotask(()=>print("before loop 2"));
    print("in event loop");
  }).then((_) {
    scheduleMicrotask(()=>print("before loop 3"));
    print("in event loop");
  });
}

it should output:它应该输出:

in event loop在事件循环中
in event loop在事件循环中
in event loop在事件循环中
before loop 1在循环 1 之前
before loop 2在循环 2 之前
before loop 3在循环 3 之前

Although i'm not sure that you can't break this optimization.虽然我不确定你不能破坏这个优化。 So only sure fact is that the first Future will complete first and the second - second.所以唯一确定的事实是第一个Future将首先完成,第二个 - 第二个。

EDIT: The strange part( Obsolete ):编辑:奇怪的部分(过时):

With code like this:用这样的代码:

import "dart:async";
void main() {
  new Future(() {
    scheduleMicrotask(print("before loop 1"));
    print("in event loop");
  }).then((_) {
    scheduleMicrotask(print("before loop 2"));
    print("in event loop");
  }).then((_) {
    scheduleMicrotask(print("before loop 3"));
    print("in event loop");
  });
}

output is:输出是:

before loop 1
in event loop
before loop 2
in event loop
before loop 3
in event loop
Unhandled exception:
The null object does not have a method 'call'.

NoSuchMethodError: method not found: 'call'
Receiver: null
...

But with this:但是有了这个:

import "dart:async";
void main() {
  new Future(() {
    scheduleMicrotask(()=>print("before loop 1"));
    print("in event loop");
  }).then((_) {
    scheduleMicrotask(()=>print("before loop 2"));
    print("in event loop");
  }).then((_) {
    scheduleMicrotask(()=>print("before loop 3"));
    print("in event loop");
  });
}

output is:输出是:

in event loop在事件循环中
in event loop在事件循环中
in event loop在事件循环中
before loop 1在循环 1 之前
before loop 2在循环 2 之前
before loop 3在循环 3 之前

EDIT2:编辑2:

I think i got it.我想我明白了。 In the first(wrong version) scheduleMicrotask actually never got properly scheduled, but since Dart has eager argument execution it executes print() anyway.在第一个(错误版本) scheduleMicrotask实际上从未被正确调度,但由于 Dart 具有急切的参数执行,它无论如何都会执行print() So what happens is that all Future getting executed in the next event loop and print all text.所以发生的事情是在下一个事件循环中执行所有Future并打印所有文本。 That's why output is in call order:这就是输出按调用顺序排列的原因:

before loop 1在循环 1 之前
in event loop在事件循环中
before loop 2在循环 2 之前
in event loop在事件循环中
before loop 3在循环 3 之前
in event loop在事件循环中

and not in the schedule order.并且不在计划顺序中。

When you do:当你这样做时:

new Future(() => 21)
.then((v) => v*2)
.then(print);
  • First you call the new Future(...) constructor.首先调用new Future(...)构造函数。 This creates a Future object and schedules a Timer to execute the function you give as argument.这将创建一个 Future 对象并安排一个Timer来执行您作为参数提供的函数。
  • Then you call then .然后你调用then This creates a new future (call it future#2) and adds a listener on the first future.这将创建一个新的未来(称之为未来#2)并在第一个未来添加一个监听器。 No events are scheduled.没有安排任何活动。
  • Then you call then again.然后你then打电话。 This creates yet another future (future#3) and adds a listener on the future#2.这创建了另一个未来(未来#3)并在未来#2 上添加了一个监听器。 No events are scheduled.没有安排任何活动。
  • Then the timer triggers, and the ()=>21 is executed, and the first future is completed with the value 21.然后定时器触发,执行()=>21 ,第一个future完成值为21。
  • The listener on the first future is then executed immediately.然后立即执行第一个未来的侦听器。 That calls (v)=>v*2 with 21, and then completes future#2 with the value 42.用 21 调用(v)=>v*2 ,然后用值 42 完成 future#2。
  • The listener on future#2 is then executed immediately.然后立即执行 future#2 上的侦听器。 That calls print with 42, which prints 42 and returns null .使用 42 调用print ,它打印 42 并返回null This completes future#3 with the value null .这完成了值为null future#3 。

Future completion is currently done through a "propagate" function that tries to complete as many futures as possible, as long as their listeners are synchronous. Future 完成目前是通过“传播”函数完成的,该函数会尝试完成尽可能多的 Future,只要它们的侦听器是同步的。 That is why completing one future will immediately complete another, without any intermediate microtasks.这就是为什么完成一个未来将立即完成另一个未来,而无需任何中间微任务。

The microtask queue is to queue async execution but avoid returning to the main event loop before these microtasks are finished.微任务队列是将异步执行排队,但避免在这些微任务完成之前返回主事件循环。 You can ensure some related activities to be completed entirely even when executed async before other async tasks/events queued in the main queue are executed.即使在执行主队列中排队的其他异步任务/事件之前异步执行,您也可以确保某些相关活动完全完成。

It seems the code executed from then like (v) => v*2 is again executed inside a Future because then always returns a Future .似乎then执行的代码像(v) => v*2再次在Future内执行,因为then总是返回Future

from https://www.dartlang.org/articles/event-loop/来自https://www.dartlang.org/articles/event-loop/

The microtask queue is necessary because event-handling code sometimes needs to complete a task later, but before returning control to the event loop.微任务队列是必要的,因为事件处理代码有时需要稍后完成任务,但在将控制权返回给事件循环之前。 For example, when an observable object changes, it groups several mutation changes together and reports them asychronously.例如,当一个 observable 对象发生变化时,它将几个突变变化组合在一起并异步报告它们。 The microtask queue allows the observable object to report these mutation changes before the DOM can show the inconsistent state.微任务队列允许 observable 对象在 DOM 显示不一致状态之前报告这些突变变化。

How I interpret this description doesn't fit with the results in the tests in @Jare 's answer.我如何解释此描述与 @Jare 答案中的测试结果不符。

Just a little thing to add to previous answers.只是要添加到以前的答案中的一点东西。 The 'Event Loop' article explains this behavior pretty well: “事件循环”文章很好地解释了这种行为:

The function that you pass into Future's then() method executes immediately when the Future completes.当 Future 完成时,您传递给 Future 的 then() 方法的函数会立即执行。 (The function isn't enqueued, it's just called.) (该函数未入队,只是被调用。)

( https://www.dartlang.org/articles/event-loop/ ) ( https://www.dartlang.org/articles/event-loop/ )

It means that in above examples there's always one event but many microtasks.这意味着在上面的例子中,总是只有一个事件,但有许多微任务。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM