Sobes.tech
Middle

O que são geradores em Dart (sync* e async*) e como eles funcionam?

sobes.tech IA

Resposta da IA

Os geradores em Dart são funções que devolvem uma sequência de valores à medida que são gerados, em vez de todo o resultado de uma vez. Utilizam as palavras-chave sync* para geradores síncronos e async* para geradores assíncronos.

Geradores síncronos (sync*)

Devolvem um objeto do tipo Iterable. Utilizam a palavra-chave yield para emitir o próximo valor. O fluxo de execução é pausado até que o próximo valor seja solicitado (por exemplo, num ciclo for-in).

Iterable<int> countUpTo(int max) sync* {
  for (int i = 1; i <= max; i++) {
    yield i; // Emite o valor
  }
}

Geradores assíncronos (async*)

Devolvem um objeto do tipo Stream. Utilizam a palavra-chave yield para emitir o próximo valor. Também usam yield* para emitir todos os valores de outro Stream. O fluxo de execução é pausado e retomado quando há um novo evento assíncrono.

Stream<int> countUpToAsync(int max) async* {
  for (int i = 1; i <= max; i++) {
    await Future.delayed(Duration(milliseconds: 100)); // Simulação de trabalho assíncrono
    yield i; // Emite o valor
  }
}

Como funcionam:

Ao chamar a função geradora, o corpo da função não é executado imediatamente. É devolvido um objeto (seja Iterable ou Stream). A execução real do corpo começa apenas quando se tenta obter o valor pela primeira vez do objeto devolvido. Quando se atinge a palavra-chave yield, o valor é passado "para fora" e o estado da função é guardado. A execução do corpo é pausada. Quando se tenta obter o próximo valor, a execução retoma de onde parou, até ao próximo yield ou ao fim da função.

Diferenças:

Característica sync* (Síncrono) async* (Assíncrono)
Tipo devolvido Iterable Stream
Palavras-chave sync*, yield async*, yield, yield*
Uso de await Não permitido Permitido
Pausa Até ao pedido do próximo valor Até à próxima ocorrência de um valor assíncrono