Funções Assíncronas
Tags: flutter, future, async, await
Published: 2021-07-02 13:31:25

_Como e quando utilizar: async | future | await | then_

## Introdução

Quando falamos sobre Flutter não podemos deixar de citar **Dart**, que é a lingaguem utilizada pelo _Framework/UIToolkit_, e que assim como outras linguagens também trabalha com funções síncronas e assíncronas que é sobre o que vamos buscar entender aqui.

<br>

## Explicando os dois tipos de funções

Explicando de uma forma mais grosseira:

> **Função Síncrona**
> ```dart
> bool tarefaFinalizada(index) {
>    final tarefaFinalizada = tarefas[index].finalizada == true;
>    return tarefaFinalizada;
> }
> ```

Uma função síncrona, assim que chamada, faz com que o sistema aguarde a execução de tudo que estiver dentro dela, para só depois continuar executando o restante das ações.
_Podemos entender ela como uma função de certa forma "normal"_

> ***

> **Função Assíncrona**
> ```dart
> Future<List<Tarefas>> getTarefas() async { 
>   // Vamos imaginar que o servidor demora 4s para retornar os dados.
>    final listaDeTarefas = await http.get('tarefas');
>    return listaDeTarefas;
> }
> ```

Uma função assíncrona, assim que chamada, não é aguardada pelo sitema para que o mesmo de continuidade em seu fluxo, ele apenas continua fazendo o que precisa em paralelo.
_Podemos entender ela como uma função que vai ser executada em paralelo com o resto do código sem travar nada e em algum momento no futuro vai retornar algum valor (Ou não)._

<br>

## Uso de algumas palavras-chaves

No caso das funções assíncronas, o **Dart** faz uso de algumas palavras-chave, que são:

> **async**
> _Indica que a função vai ser assíncrona e em algum momento, dentro dela, talvez seja preciso esperar para pegar algum dado._

> ***

<br>

> **future**
> _Informa que a função vai retornar um dado do futuro, necessário quando utilizamos a palavra-chave **async**._

> ***

<br>

> **Exemplo**
> ```dart
> Future<Exterminator> getExterminator() async {
>   final buscarExterminador = await http.get('exterminator');
>   return buscarExterminador;
> }
> ```
 
Quando utilizamos funções assíncronas, precisamos utilizar o **async** e o **Future** para indicar que aquela função vai retornar um valor no "futuro", como por exemplo: Um retorno do servidor de SUCESSO ou ERRO após 5 segundos.

> **await**
_Faz com que o sistema espere naquela determinada linha até o término da função._

> ***

<br>

> **then**
> _É uma função anônima (lambda) que só é executada quando a função assíncrona, a qual ela está vinculada, terminar._

> ***

<br>

> **Exemplo**
> ```dart
> Future<void> iniciarSkynet() async { 
>    final inicializacaoBemSucedida = await http.put('initialize', data: { "code": 0001 });
>    if (inicializacaoBemSucedida) {
>      getExterminator().then((Exterminator exterminator){
>        exterminator.initializeProtocolZero();
>        print("inicializado")
>      });
>    }
>    print("log de inicialização")
> }
>```

Utilizamos o **await** quando fazemos chamadas que retornem um **Future** e queremos que o sistema espere pelo retorno para que execute o resto das coisas.
Já o **then** usamos quando fazemos chamadas que retornem um **Future**, mas não queremos esperar seu resultado e sim executar alguma outra coisa apenas no final, deixando assim o fluxo seguir.

## Casos de uso

_Vamos entender na prática, quando utilizar cada uma das palavras-chave, utilizando um exemplo de login._

A ideia é que após preenhido os campos (Usuario e senha), a aplicação busque o usuário no servidor e retorne o nome do mesmo, com isso vamos poder saber se o usuário existe para permitir o acesso e caso não exista, podemos preenche-las no primeiro acesso.

> Entenda cada expressão da seguinte forma:
> * **print(“ ”)** como se fosse uma ação visual que está sendo exibida ao usuário em tela.
> * **Future.delayed()** delays de conexão com o servidor.
Apenas para fins didáticos.

```dart

// Início do sistema
void main() {
   
  fazerLoginComFeedback();

}

Future<void> fazerLoginComFeedback() async {
  
   //Aguarda a função que fará contato com o servidor retornar o nome do usuário
   String nomeUsuario = await getUsuario("matheus", "1234");
  
   // Verifica se o usuário foi encontrado
   if (nomeUsuario == "") {
     print("Usuário não encontrado!");
   } else {
     
     //Exibe uma mensagem de boas-vindas com o nome do usuário retornado pelo servidor
     exibirFeedbackVisual(nomeUsuario);
       
     // Busca os dados do usuário do banco de dados e quando terminar exibe a tela principal
     pegarDados(nomeUsuario).then((dados) { 
       print(dados);
       
       // Após exibir a mensagem muda para a tela inicial
       print("Abrindo tela inicial.");
       
     });
     
   }
}

// Função assíncrona
Future<String> getUsuario(String login, String senha) async {
  print("Buscando usuário...");
  
  // Requisição ao servidor para saber se o usuário existe
  await Future.delayed(Duration(milliseconds: 2000));

  // Usuário encontrado
  String usuario = "Matheus Ribeiro";

  return usuario;
  
}

// Função síncrona
void exibirFeedbackVisual(String nomeUsuario) {
  print("Bem vindo, $nomeUsuario");
}

// Função assíncrona
Future<String> pegarDados(String usuario) async {
  print("Buscando dados do $usuario...");
  
  // Executa algumas consultas no banco para retornar os dados
  await Future.delayed(Duration(milliseconds: 2000));
  
  // Dados encontrados
  String dadosUsuario = '{"id":1, "email": "usuario@email.com.br"}';
  
  print("Armazena os dados em memória");
  
  return dadosUsuario;
}

```

Como podemos ver, o grande foco do exemplo é o método **fazerLoginComFeedback()**.

Dentro dele podemos ver as diferentes formas de tratar funções assíncronas, utilizando tanto o **await** quanto o **then**.

> Ambos podem retornar o mesmo resultado, só que necessitam de tratamentos diferentes.

Podemos ver também a chamada da função **getUsuario()** utilizando o **await**, pois ali precisamos esperar o resultado da requisição para tomar alguma decisão no processo.

Já a chamada **pegarDados()** utilizamos o **then** porque essa função vai apenas buscar os dados no banco de dados e armazenar em memória para serem exibidos na próxima tela (Tela inicial)

<br>

______

## <center> FIM </center>
_<center> Espero ter conseguido explicar de uma forma clara e objetiva.</center>_

______