# Explorando funções assíncronas no Javascript

Hoje vamos explorar a sincronicidade no Javascript? Você sabe como utilizar uma função assíncrona?

## Programação Assíncrona

Se você já realizou alguma ação em seu código, e teve que esperar uma resposta —por exemplo, um fetch a uma API, você já trabalhou com programação assíncrona.

Sincronicidade no Javascript, é quando precisamos trabalhar com uma função que acontece em segundo plano, enquanto o restante do nosso código continua a rodar normalmente.

Na prática, isso pode parecer um pouco estranho, afinal estamos acostumados com uma linha de código rodando atrás da outra.

Veja o exemplo:

```jsx
const mensagemAposSegundos = (mensagem, segundos) => {
  setTimeout(() => {
    console.log(mensagem);
  }, segundos * 1000);
}

const iniciaPrograma = () => {
  mensagemAposSegundos('mensagem 1', 2);
  mensagemAposSegundos('mensagem 2', 1);
}

iniciaPrograma();

```

No código acima, criei a função `mensagemAposSegundos` que escreve no console uma mensagem qualquer após x segundos. Veja utilizei essa função 2 vezes, querendo escrever a “mensagem 1” após 2 segundos e a “mensagem 2” após 1 segundos.

Lendo este código naturalmente, sem pensar em sincronicidade, o esperado seria o meu programa começar a rodar e após 2 segundos a “mensagem 1” ser exibida. Depois de mais 1 segundo, teríamos a “mensagem 2” no console. Mas, na prática, a resposta é:

```
mensagem 2
mensagem 1
```

Pode parecer estranho, mas com Javascript, o que acontece é: a primeira função para exibir a “mensagem 1” é lida, e começa a rodar em segundo plano. Enquanto isso, o código já passa para a linha seguinte, onde é chamada a função para exibir a “mensagem 2” e também começa a rodar em segundo plano. Como a “mensagem 2” precisa de apenas 1 segundo para ser exibida, ela acontece primeiro, e só depois de 2 segundos a “mensagem 1” é exibida.

Em alguns casos, queremos que o código exibido na ordem correta, e precisamos pedir para “esperar” a função terminar para ir a próxima linha. Com Javascript, precisamos transformar essa em função comum em uma função assíncrona, utilizando os recursos de async, await e promises.

## Async, await e Promises

Uma função assíncrona em Javascript é uma `Promise`, um método que “promete” de entregar um resultado, seja ele positivo com um `resolve` ou negativo com um `reject`. Ao chamar uma função que retorna uma `Promise`, transformo essa função em assíncrona, e posso pedir ao código que “espere” essa função terminar, utilizando o prefixo `await` ou o método `then` para resultados positivos e `catch` para resultados negativos.

<aside>
🚨 Importante: só é possível utilizar o prefixo `await` dentro de uma função assíncrona.

</aside>

Em nosso exemplo anterior, para funcionar como esperado, precisamos criar uma `Promise` na função `mensagemAposSegundos`, prometendo sinalizar a conclusão dessa função somente após a exibição da mensagem. Assim, ao chamar a função posso pedir explicitamente ao código para esperar ser concluída com `await` ou realize uma ação após a sua conclusão com `then`

```jsx
const mensagemAposSegundos = async (mensagem, segundos) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(mensagem);
      resolve();
    }, segundos * 1000);
  });
}

const iniciaPrograma = async () => {
  await mensagemAposSegundos('mensagem 1', 2);
  await mensagemAposSegundos('mensagem 2', 1);

	//ou

  mensagemAposSegundos('mensagem 1', 2).then(() => {
    mensagemAposSegundos('mensagem 2', 1);
  });
}

iniciaPrograma();

```

Desta forma, estamos indicando que a nossa função, que promete entregar um resultado com a `Promise` só é concluída, a partir do `resolve()`, após a exibição da mensagem. Como ela é uma função assíncrona, marcada com `async`, podemos pedir para esperar a função ser concluída com `await`, ou criar uma árvore de resultados com `then`, chamando a segunda mensagem somente após a primeira ter sido concluída. Tendo como resultado:

```
mensagem 1
mensagem 2
```

## Na prática

Funções assíncronas e `Promises` já são bastante comuns durante o desenvolvimento, seja em uma API quando você cria um registro no banco de dados, ou seja, no frontend quando há uma requisição para uma API. Essas funções devem ser usadas com bastante cuidado para não “dessincronizar o seu código”.

No exemplo abaixo, você tem uma função fetch, para pegar os dados de um usuário a partir de um endpoint de uma API e conferir se este usuário está logado.

```jsx
const isUserLogged = (userId) => {
  const response = fetch(`https://example.com/api/user/${userId}`);
  const user = response.json();

  return user.isLogged;
}
```

Neste formato, sua função estaria errada. O `fetch` e a resposta do `fetch` são `Promises`, ou seja, são funções assíncronas, que acontecem apenas em segundo plano. Sem um pedido explicito de pedido de espera de finalização dessa função, a variável `user` estará vazia, ainda sem resposta, no retorno `user.isLogged`. O correto é algo como:

```jsx
const isUserLogged = async (userId) => {
  const response = await fetch(`https://example.com/api/user/${userId}`);
  const user = await response.json();

  return user.isLogged;
}
```

Dessa forma, estamos solicitando que o código espere a função `fetch` ser finalizada, e espere a resposta ser transformada em JSON com `response.json()`. Assim, ao ter a variável `user` lida em `user.isLogged` todos, os dados estarão presentes.

Este é um assunto bastante importante para desenvolvedores iniciantes, e veja que um pequeno deslize no código pode deixar tudo bastante confuso; por isso, é importante sempre ter bastante atenção no uso de Promises, Asyncs e Awaits, mas principalmente, entender o que realmente está acontecendo por trás dos códigos. Estudar estes conceitos da linguagem com certeza irão resultar em melhores códigos em seus projetos.

Para ficar por dentro dos nossos próximos conteúdos, participe do nosso canal no Discord e se inscreva em nossa newsletter!
