# Functions assíncronas

## Visão geral

A maior parte do código na sua scene é executada de forma síncrona usando uma única thread. Isso significa que os comandos são executados sequencialmente, linha por linha. Cada comando precisa primeiro esperar que o comando anterior termine de ser executado antes de poder começar.

Até mesmo as funções nos systems da sua scene são executadas uma por uma, seguindo uma [ordem de prioridade](/creator/content-creator-pt/scenes-sdk7/arquitetura/systems.md#system-execution-order).

Executar o código de forma síncrona garante consistência, pois você sempre pode ter certeza de que saberá a ordem em que os comandos no seu código são executados.

Por outro lado, sua scene precisa ser atualizada muitas vezes por segundo, construindo o próximo frame. Se uma parte do seu código demorar demais para responder, então a thread principal inteira fica bloqueada e isso resulta em taxas de frames com lag.

É por isso que, em alguns casos, você quer que alguns comandos sejam executados de forma assíncrona. Isso significa que você pode iniciar uma tarefa em uma nova thread e, enquanto isso, a thread principal pode continuar executando as próximas linhas de código.

Isso é especialmente útil para tarefas que dependem de serviços externos que podem levar tempo para responder, já que você não quer que esse tempo ocioso de espera pela resposta bloqueie outras tarefas.

Por exemplo:

* Ao recuperar dados de uma REST API
* Ao realizar uma transação na blockchain

{% hint style="warning" %}
**📔 Nota**: Tenha em mente que vários frames da sua scene podem ser renderizados antes que a tarefa termine de ser executada. Certifique-se de que o código da sua scene seja flexível o suficiente para lidar com os cenários intermediários enquanto a tarefa assíncrona está sendo concluída.
{% endhint %}

## Executar uma função assíncrona

Marque qualquer função como `async` para que ela seja executada em uma thread separada da thread principal da scene toda vez que for chamada.

```ts
// declarar função assíncrona
async function myAsyncTask() {
	// executar as etapas da função
}

// chamar função assíncrona
myAsyncTask()

// o restante do código continua sendo executado
```

## A função executeTask

O `executeTask()` a função executa uma função lambda de forma assíncrona, em uma thread separada da thread principal da scene. `executeTask()` permite-nos declarar e executar a função tudo em uma única mesma instrução.

```ts
executeTask(async () => {
	let data = await myAsyncTask()
	console.log(data)
})

// o restante do código continua sendo executado
```

## A função then

O `then` a função recebe uma função lambda como argumento, que só é executada quando a instrução anterior é concluída. Essa função lambda pode opcionalmente ter entradas mapeadas a partir do que a instrução anterior retorna.

```ts
myAsyncTask().then((data) => {
	console.log(data)
})
```

{% hint style="warning" %}
**📔 Nota**: Geralmente é melhor usar a abordagem `executeTask` em vez da função `then` function. Neste exemplo, a scene não será considerada totalmente carregada pelo explorer até que a `myAsyncTask()` function seja concluída, o que pode afetar os tempos de carregamento. Além disso, se depender demais da função `then` em vários níveis aninhados, você pode acabar com o que é conhecido como "callback hell", onde o código pode se tornar muito difícil de ler e manter.
{% endhint %}

## Funções PointerEvents e RayCast

Quando sua scene usa um `PointerEvent` ou um `RayCast` component, os cálculos de colisões são realizados de forma assíncrona no engine. O engine então retorna um evento de resultados para a scene, que pode chegar um ou vários ticks do game loop depois de quando o evento foi invocado.

Você então precisa criar um system para processar esses resultados no frame em que eles chegarem.

{% hint style="warning" %}
**📔 Nota**: Se você lidar com cliques por meio da abordagem [**Register a callback**](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/register-callback.md) você não precisa criar explicitamente um system para lidar com isso, mas o mesmo ocorre em segundo plano.
{% endhint %}

Consulte [eventos de clique](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/click-events.md) e [raycasting](/creator/content-creator-pt/scenes-sdk7/interatividade/raycasting.md).

{% hint style="info" %}
**💡 Dica**: Se o processamento dos resultados de um raycast exigir muitos cálculos (como executar um algoritmo de path-finding), talvez você queira executar esse cálculo em uma função assíncrona.
{% endhint %}

## A instrução await

Um `await` a instrução força a execução a esperar por uma resposta antes de avançar para a próxima linha de código. `await` as instruções só podem ser usadas dentro de um bloco de código async.

```ts
// declarar função
async function myAsyncTask() {
	try {
		let response = await fetch(callUrl)
		let json = await response.json()
		console.log(json)
	} catch {
		console.log('falhou ao acessar a URL')
	}
}

// chamar a função
myAsyncTask()

// o restante do código continua sendo executado
```

O exemplo acima executa uma função que inclui uma `fetch()` operação para recuperar dados de uma API externa. A `fetch()` operação é assíncrona, pois não podemos prever quanto tempo o servidor levará para responder. No entanto, a próxima linha precisa que a saída dessa operação esteja pronta antes de podermos analisá-la como um json. A `await` instrução aqui garante que a próxima linha só será executada depois que essa operação retornar um valor. Da mesma forma, a `response.json()` função também é assíncrona, mas a próxima linha precisa que o json seja analisado antes de poder registrá-lo. A segunda `await` instrução força a próxima linha a ser chamada somente depois que a análise do json for concluída, independentemente de quanto tempo isso leve.

## Definir um Timeout para uma chamada de função

Use `setTimeout` para esperar algum tempo antes que certas linhas de código sejam executadas. Isso leva dois argumentos:

* A função a executar
* A quantidade de milissegundos a esperar antes de executar essa função

O exemplo abaixo espera 1000 milissegundos (equivalente a 1 segundo) antes de executar uma função simples que registra uma mensagem no console.

```ts
import { timers } from '@dcl/sdk/ecs'

console.log('Isso é impresso imediatamente')

timers.setTimeout(() => {
	// função para executar após atraso
    console.log('Isso é impresso após 1 segundo')
}, 1000)
```

O `clearTimeout` pode ser usado para cancelar a execução de uma `setTimeout` função que ainda está aguardando para ser executada. Ao criar a `setTimeout` função, pegue uma referência à função, que você pode então passar para `clearTimeout`. Nesse caso, a variável `intervalId` é obtida ao fazer o `setTimeout`, e então passada para `clearTimeout` para cancelá-la.

```ts
import { timers } from '@dcl/sdk/ecs'

const timeoutId = timers.setTimeout(() => {
    console.log('Espere 1 segundo até executar esta função')
}, 1000)

timers.clearTimeout(intervalId)
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/padroes-de-programacao/async-functions.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
