A maioria dos desenvolvedores Dart não entende como o await funciona — você é um deles?

Quando comecei com Dart, cometi o mesmo erro que muitos desenvolvedores: eu achava que o await simplesmente pausava o código, como uma função sleep. Fazia sentido… até deixar de fazer.

Se você já ficou confuso sobre por que um código com await executa antes ou depois de coisas que você não esperava, ou se perguntou se ele bloqueia a interface (UI) — você está fazendo as perguntas certas.

Neste guia curto, vou te mostrar o que o await realmente faz, como o Dart agenda o código assíncrono “por baixo do capô” e por que entender isso é essencial se você quer escrever aplicativos Flutter fluidos e sem bugs.

O await para a thread de UI?

Não, o await não bloqueia a thread de UI. Quando você usa await, o Dart pausa a sua função — mas não o aplicativo. A interface continua responsiva, as animações rodam e a entrada do usuário ainda funciona.

Assim que a Future é concluída, o Dart retoma sua função como uma microtask, que executa antes dos eventos normais na fila.

E é aqui que a maioria dos desenvolvedores — inclusive eu, quando comecei — se atrapalha. Você escreve um código assíncrono, espalha alguns awaits e, de repente, seu app se comporta de forma imprevisível. Por que aquela linha executou primeiro? Por que o diálogo não apareceu? Tudo se resume a quando e como o Dart decide rodar seu código — e é aí que entra o Event Loop.

Antes de prosseguirmos, vamos fazer um pequeno teste. Olhe para o seguinte código Dart e tente adivinhar a ordem da saída no console:

void main() async {
  print('1. start');

  Future(() => print('2. event queue task'));

  scheduleMicrotask(() => print('3. microtask'));

  await Future.delayed(Duration(milliseconds: 1));

  print('4. after await');
}

Qual você acha que será a saída?
A maioria dos desenvolvedores — incluindo eu, no início — espera:

1. start  
2. event queue task  
3. microtask  
4. after await

Mas o Dart tem um plano diferente. Vamos analisar por que essa suposição está errada e o que realmente está acontecendo por baixo do capô.

O Event Loop do Dart: Duas Filas que Você Precisa Conhecer

O Dart utiliza um event loop de thread única com duas filas de tarefas principais:

  1. Fila de Microtarefas (Microtask Queue) — Alta prioridade

    • Usada por: await, Future.microtask(), scheduleMicrotask().

  2. Fila de Eventos (Event Queue) — Prioridade normal

    • Usada por: Future(() {}), timers, gestos, streams, etc.

Como o Dart Agenda a Execução

  1. Executa todo o código síncrono atual.

  2. Processa todas as microtarefas.

  3. Processa uma tarefa da fila de eventos.

  4. Repete o processo.

É por isso que alguns códigos parecem estar ‘fora de ordem’ — é apenas o event loop fazendo o seu trabalho.

Saída Real:

1. start
3. microtask
2. event queue task
4. after await.
  • print('1. start') executa de forma síncrona.

  • scheduleMicrotask(...) adiciona print('3. microtask') à fila de microtarefas (microtask queue).

  • Future(() => ...) adiciona print('2. event queue task') à fila de eventos (event queue).

  • O Dart finaliza o código síncrono e executa todas as microtarefasprint('3. microtask').

  • Em seguida, ele executa 1 evento da fila de eventos → print('2. event queue task').

  • Quando o await termina, ele retoma sua função como uma microtarefaprint('4. after await').

Mas você pode dizer que print('4. after await') é uma linha síncrona — e você estaria certo. Só que aqui está o “pulo do gato”:

Assim que sua função encontra um await, o Dart não apenas “pausa e continua” como você esperaria. Em vez disso, tudo o que vem depois daquele await — mesmo que seja um código síncrono — é agendado para rodar depois, como uma microtarefa.

Isso significa que o print('4. after await') não executa imediatamente após a linha anterior. Ele executa apenas depois que:

  1. Todas as microtarefas na fila atual terminam;

  2. Uma tarefa da fila de eventos seja processada (se houver);

  3. A Future aguardada pelo await seja concluída.

Portanto, embora a linha em si seja síncrona, ela é executada assincronamente, porque a função retoma sua execução dentro da fila de microtarefas.

É por isso que o print('4. after await') aparece depois tanto da microtarefa quanto da tarefa da fila de eventos — o que importa é quando o Dart retoma sua função, e não o tipo de código que vem a seguir.

Da próxima vez que você escrever código assíncrono, você não estará apenas esperando — você saberá exatamente o que está acontecendo por baixo do capô.

Achou isso útil? Compartilhe com seu círculo de devs e siga para mais mergulhos profundos no mundo real do Flutter.

Please follow and like us:
error0
fb-share-icon
Tweet 20
fb-share-icon20