Assincrona e Promise
Assincrona e Promise
Assíncronas em JavaScript:
Definição:
- Operações assíncronas permitem que o programa continue a executar outras tarefas enquanto aguarda a conclusão de operações demoradas, como requisições de rede ou leitura de arquivos.
Mecanismos de Assincronicidade:
- Callbacks, Promises e Async/Await são mecanismos comuns para lidar com operações assíncronas.
Promises:
Definição:
- Promises são objetos que representam a conclusão ou falha eventual de uma operação assíncrona. Elas fornecem uma maneira mais estruturada de lidar com o código assíncrono.
Estados:
- Pendente: Estado inicial, a operação ainda não foi concluída.
- Resolvida (Fulfilled): A operação foi concluída com sucesso.
- Rejeitada (Rejected): A operação falhou.
Métodos Principais:
then()
: Tratamento bem-sucedido.catch()
: Tratamento de falhas.finally()
: Executa sempre, independentemente do resultado.
Exemplo de Promise:
const minhaPromise = new Promise((resolve, reject) => { // Simula uma operação assíncrona setTimeout(() => { const sucesso = true; if (sucesso) { resolve('Operação concluída com sucesso!'); } else { reject('Erro na operação!'); } }, 2000); }); minhaPromise .then((resultado) => console.log(resultado)) .catch((erro) => console.error(erro)) .finally(() => console.log('Sempre executado.'));
As Promises e a assincronicidade são fundamentais para lidar com operações demoradas de forma eficiente em JavaScript, garantindo uma execução suave e responsiva do código.
setTimeout
e clearTimeout
setTimeout
:
Definição:
- A função
setTimeout
é utilizada para agendar a execução de uma função ou código após um determinado intervalo de tempo, especificado em milissegundos.
- A função
Sintaxe:
const timeoutId = setTimeout(funcao, tempoDeEspera);
Exemplo:
function exibirMensagem() { console.log('Executado após 2000ms'); } const timeoutId = setTimeout(exibirMensagem, 2000);
clearTimeout
:
Definição:
- A função
clearTimeout
é utilizada para cancelar a execução de uma função agendada comsetTimeout
, impedindo que ela ocorra.
- A função
Sintaxe:
clearTimeout(timeoutId);
Exemplo:
function exibirMensagem() { console.log('Executado após 2000ms'); } const timeoutId = setTimeout(exibirMensagem, 2000); // Cancela a execução agendada clearTimeout(timeoutId);
Funcionamento:
setTimeout
:- Aguarda o tempo especificado (
tempoDeEspera
) e, em seguida, executa a função fornecida (funcao
).
- Aguarda o tempo especificado (
clearTimeout
:- Utiliza o identificador de timeout (
timeoutId
) para cancelar a execução agendada antes que ela ocorra.
- Utiliza o identificador de timeout (
Uso Comum:
Atrasos Assíncronos:
- Útil para criar atrasos em operações assíncronas ou para agendar tarefas após um intervalo específico.
Feedback ao Usuário:
- Pode ser usado para exibir mensagens temporárias ou notificações em interfaces de usuário.
Considerações Importantes:
Identificador Único:
- O identificador retornado por
setTimeout
é único e é utilizado porclearTimeout
para cancelar o timeout específico.
- O identificador retornado por
Atraso Mínimo:
- O tempo de espera em
setTimeout
não é garantido; a execução ocorre após, no mínimo, o tempo especificado.
- O tempo de espera em
Uso Responsável:
- Deve-se ter cuidado ao utilizar
setTimeout
para evitar ações indesejadas ou vazamentos de memória.
- Deve-se ter cuidado ao utilizar
O setTimeout
e o clearTimeout
são ferramentas úteis para lidar com a execução de código em intervalos específicos ou para criar atrasos na execução de funções. Eles são frequentemente utilizados em cenários em que é necessário agendar tarefas para ocorrerem após um intervalo de tempo específico.
Comparação entre Síncrono e Assíncrono em JavaScript:
Síncrono:
Execução Bloqueante:
- As operações são realizadas uma após a outra, bloqueando a execução até a conclusão de cada tarefa.
Fluxo de Controle Linear:
- O código é executado de maneira sequencial, seguindo uma ordem específica.
Possível Espera Ativa:
- Pode resultar em espera ativa, onde o programa aguarda a conclusão de uma tarefa antes de iniciar outra.
Exemplo:
console.log('Início'); for (let i = 0; i < 3; i++) { console.log(i); } console.log('Fim');
Saída:
Início 0 1 2 Fim
Assíncrono:
Execução Não-Bloqueante:
- Permite que operações sejam realizadas em paralelo, sem bloquear a execução do restante do código.
Callbacks, Promises, Async/Await:
- Mecanismos como callbacks, promises e async/await são utilizados para lidar com operações assíncronas.
Melhor Desempenho em Operações Demoradas:
- Útil para operações que levam tempo, como requisições de rede, leitura de arquivos, etc.
Exemplo com Callback:
console.log('Início'); setTimeout(() => { console.log('Tarefa Assíncrona Concluída'); }, 2000); console.log('Fim');
Saída:
Início Fim Tarefa Assíncrona Concluída
Considerações Gerais:
Síncrono:
- Simplicidade no fluxo de controle.
- Bloqueio durante operações demoradas.
Assíncrono:
- Melhor desempenho em operações demoradas.
- Complexidade adicional de gerenciamento de assincronicidade.
A escolha entre abordagens síncronas e assíncronas depende das necessidades específicas da aplicação. Operações rápidas e sequenciais podem se beneficiar da simplicidade síncrona, enquanto operações demoradas e paralelas podem ser mais eficientemente tratadas de forma assíncrona para evitar bloqueios desnecessários. O JavaScript oferece uma variedade de mecanismos para lidar com ambos os casos.
Call Stack (Pilha de Chamadas)
A call stack, ou pilha de chamadas, é uma estrutura de dados em JavaScript que gerencia a execução de funções. Ela segue o princípio Last In, First Out (LIFO), onde a última função adicionada à pilha é a primeira a ser removida. A call stack mantém o controle do contexto de execução durante a execução de um programa.
Funcionamento:
Chamada de Função:
- Quando uma função é chamada, um novo frame (quadro) é criado e colocado no topo da pilha, representando a execução dessa função.
Execução:
- O código da função é executado dentro do contexto desse frame.
Retorno da Função:
- Quando a função é concluída, seu frame é removido da pilha, retornando o controle para a função chamadora.
LIFO (Last In, First Out):
- A pilha opera seguindo a lógica LIFO, onde a última função adicionada é a primeira a ser removida.
Exemplo Simples:
function funcaoA() {
console.log('Função A');
}
function funcaoB() {
funcaoA();
console.log('Função B');
}
funcaoB();
Pilha de Chamadas:
funcaoB
é chamada, adicionando seu frame à pilha.funcaoA
é chamada de dentro defuncaoB
, adicionando seu frame à pilha.funcaoA
conclui sua execução, removendo seu frame da pilha.funcaoB
continua a execução após a chamada defuncaoA
e conclui, removendo seu frame da pilha.
Uso na Detecção de Erros:
- A call stack é fundamental para a detecção de erros e rastreamento de pilhas de chamadas em mensagens de erro, auxiliando na identificação de onde ocorreu um problema.
Considerações Importantes:
- A pilha pode ficar cheia em casos de recursão excessiva ou loops infinitos, resultando em um erro de estouro de pilha (stack overflow).
- Operações assíncronas, como callbacks e promessas, são tratadas através da Web API e da fila de eventos, não diretamente na pilha de chamadas.
A call stack desempenha um papel crucial no gerenciamento do fluxo de execução em JavaScript, rastreando as chamadas de funções e garantindo que o código seja executado de maneira organizada e controlada.
Event Loop
O Event Loop (Laço de Eventos) é um mecanismo essencial em linguagens de programação assíncronas, como JavaScript. Ele gerencia a execução de código, garantindo a não bloqueação do thread principal e permitindo a resposta a eventos assíncronos, como requisições de rede, operações de leitura/escrita e eventos do usuário.
Funcionamento Básico:
Call Stack (Pilha de Chamadas):
- O código JavaScript é executado na call stack, uma estrutura de dados que mantém o contexto de execução das funções.
Eventos e Callbacks:
- Quando ocorrem eventos assíncronos (como cliques do mouse, requisições de rede ou temporizadores), os callbacks correspondentes são colocados em filas de eventos.
Callback Queue (Fila de Callbacks):
- Os callbacks aguardam na fila de eventos até que a call stack esteja vazia.
Verificação do Event Loop:
- O Event Loop verifica continuamente se a call stack está vazia. Se estiver vazia, ele pega o próximo callback da fila de eventos e o coloca na call stack para execução.
Execução do Callback:
- O callback é executado, e o processo se repete.
Exemplo Simples:
console.log('Início');
setTimeout(() => {
console.log('Temporizador Executado');
}, 2000);
console.log('Fim');
Saída Esperada:
Início
Fim
Temporizador Executado
Uso em Operações Assíncronas:
Requisições de Rede:
- O Event Loop permite que o código continue executando enquanto aguarda a resposta de uma requisição de rede.
Temporizadores:
- Operações como
setTimeout
são gerenciadas pelo Event Loop, permitindo que outras tarefas sejam executadas durante a contagem regressiva.
- Operações como
Considerações Importantes:
Single Thread:
- JavaScript é uma linguagem single-threaded, o que significa que tem apenas um thread de execução principal.
Não Bloqueante:
- O Event Loop torna o JavaScript não bloqueante, permitindo que operações assíncronas sejam tratadas sem interromper a execução do código.
Microtasks:
- Microtasks, como Promises, têm prioridade sobre macrotasks (callbacks de temporizadores, eventos do usuário) na fila de eventos.
O Event Loop é crucial para o funcionamento assíncrono eficiente do JavaScript, permitindo a execução de código assíncrono sem bloquear o thread principal. Ele desempenha um papel vital no gerenciamento de eventos e na manutenção da responsividade em aplicações web e outras operações assíncronas.
setInterval
e clearInterval
setInterval
:
Definição:
- A função
setInterval
é utilizada para repetir a execução de uma função ou código em intervalos regulares, especificados em milissegundos.
- A função
Sintaxe:
const intervalId = setInterval(funcao, intervalo);
Exemplo:
function exibirMensagem() { console.log('Executado a cada 1000ms'); } const intervalId = setInterval(exibirMensagem, 1000);
clearInterval
:
Definição:
- A função
clearInterval
é usada para interromper a execução de um intervalo configurado comsetInterval
.
- A função
Sintaxe:
clearInterval(intervalId);
Exemplo:
function exibirMensagem() { console.log('Executado a cada 1000ms'); } const intervalId = setInterval(exibirMensagem, 1000); // Após 5000ms, interrompe o intervalo setTimeout(() => { clearInterval(intervalId); console.log('Intervalo interrompido após 5000ms'); }, 5000);
Funcionamento:
setInterval
:- Inicia a execução da função em intervalos regulares, criando um identificador de intervalo (
intervalId
).
- Inicia a execução da função em intervalos regulares, criando um identificador de intervalo (
clearInterval
:- Utiliza o identificador do intervalo para interromper a execução repetitiva configurada com
setInterval
.
- Utiliza o identificador do intervalo para interromper a execução repetitiva configurada com
Uso Comum:
Animações:
- Pode ser utilizado para criar animações com atualizações regulares.
Atualizações Periódicas:
- Útil para atualizar dados ou conteúdo em intervalos específicos.
Considerações Importantes:
Atraso Inicial:
- O intervalo definido em
setInterval
é o tempo entre as execuções sucessivas, mas a primeira execução ocorre imediatamente.
- O intervalo definido em
Identificador Único:
- O identificador retornado por
setInterval
é único e é utilizado peloclearInterval
para interromper o intervalo específico.
- O identificador retornado por
Uso Responsável:
- Deve-se ter cuidado ao utilizar
setInterval
para evitar vazamentos de memória e garantir a eficiência do código.
- Deve-se ter cuidado ao utilizar
O setInterval
e o clearInterval
são mecanismos úteis para a execução repetitiva de código em intervalos específicos. Eles são comumente utilizados em situações em que é necessário realizar ações de forma periódica, como animações ou atualizações automáticas.
then
, catch
, e finally
em Promises
then
:
Definição:
- O método
then
é usado em Promises para lidar com o resultado bem-sucedido de uma operação assíncrona.
- O método
Sintaxe:
minhaPromise.then( // Função de sucesso (resolve) resultado => { // Código a ser executado em caso de sucesso } );
Uso:
- A função passada para
then
é executada quando a Promise é resolvida com sucesso, recebendo o resultado como argumento.
- A função passada para
catch
:
Definição:
- O método
catch
é utilizado para lidar com erros (rejeições) em Promises.
- O método
Sintaxe:
minhaPromise.catch( // Função de erro (reject) erro => { // Código a ser executado em caso de erro } );
Uso:
- A função passada para
catch
é executada quando a Promise é rejeitada, recebendo o motivo do erro como argumento.
- A função passada para
finally
:
Definição:
- O método
finally
é usado para executar código independentemente de a Promise ser resolvida ou rejeitada.
- O método
Sintaxe:
minhaPromise.finally(() => { // Código a ser executado sempre, seja resolvida ou rejeitada });
Uso:
- A função passada para
finally
será sempre executada, independentemente de a Promise ser resolvida ou rejeitada.
- A função passada para
then
e catch
:
Encadeamento de Encadeamento:
- É comum encadear vários
then
para lidar com resultados sucessivos e usarcatch
no final para lidar com qualquer erro que ocorra em qualquer ponto da cadeia.
minhaPromise .then(resultado1 => { // Código para resultado1 return resultado2; }) .then(resultado2 => { // Código para resultado2 return resultado3; }) .then(resultado3 => { // Código para resultado3 }) .catch(erro => { // Código para tratar erros em qualquer ponto da cadeia });
- É comum encadear vários
Uso Típico:
- Operações Assíncronas:
then
é usado para tratar o sucesso de uma operação assíncrona.catch
é utilizado para lidar com erros durante a execução da operação.finally
é empregado para executar código que deve ser realizado independentemente do resultado da Promise.
Considerações Importantes:
- Ordem de Execução:
- As funções passadas para
then
,catch
efinally
são enfileiradas para execução após
- As funções passadas para
a conclusão da Promise correspondente.
Encadeamento Assíncrono:
- O encadeamento de
then
permite criar sequências assíncronas, garantindo que cada parte do código aguarde a resolução anterior.
- O encadeamento de
Propagação de Erros:
- Erros não tratados em qualquer ponto do encadeamento serão capturados pelo primeiro bloco
catch
encontrado na cadeia.
- Erros não tratados em qualquer ponto do encadeamento serão capturados pelo primeiro bloco
finally
e Encadeamento:- O bloco
finally
pode ser usado no final do encadeamento para realizar ações independentemente do sucesso ou falha, evitando repetições de código.
- O bloco
Os métodos then
, catch
, e finally
são fundamentais no trabalho com Promises em JavaScript, proporcionando controle eficiente sobre o fluxo de execução assíncrona e permitindo o tratamento adequado de resultados bem-sucedidos, erros e ações que devem ser realizadas independentemente do resultado da Promise.
try
e catch
try
:
Definição:
- O bloco
try
é usado para envolver uma seção de código onde exceções (erros) podem ocorrer.
- O bloco
Sintaxe:
try { // Código onde exceções podem ocorrer } catch (erro) { // Bloco executado em caso de exceção }
Uso:
- O código dentro do bloco
try
é monitorado quanto a erros. Se ocorrer algum erro, a execução é interrompida, e o controle passa para o blococatch
.
- O código dentro do bloco
catch
:
Definição:
- O bloco
catch
é utilizado para lidar com exceções (erros) que podem ocorrer dentro do blocotry
.
- O bloco
Sintaxe:
try { // Código onde exceções podem ocorrer } catch (erro) { // Bloco executado em caso de exceção // 'erro' contém informações sobre a exceção }
Uso:
- O código dentro do bloco
catch
é executado se ocorrer uma exceção no blocotry
. O parâmetroerro
contém informações sobre a exceção.
- O código dentro do bloco
Exemplo:
try {
// Código potencialmente problemático
const resultado = dividir(10, 0);
console.log('Resultado:', resultado);
} catch (erro) {
// Tratamento de exceção
console.error('Erro:', erro.message);
}
function dividir(dividendo, divisor) {
if (divisor === 0) {
throw new Error('Divisão por zero não permitida');
}
return dividendo / divisor;
}
Uso Típico:
Tratamento de Exceções:
- Utilizado para encapsular código onde podem ocorrer exceções e fornecer um mecanismo de tratamento para lidar com essas exceções.
Evitar Interrupção:
- Ajuda a evitar que um erro em uma parte do código interrompa a execução global do programa.
Considerações Importantes:
Lançamento de Exceções:
- O operador
throw
é utilizado para lançar exceções dentro do blocotry
, e o controle é transferido para o blococatch
.
- O operador
Múltiplos Blocos
catch
:- É possível ter vários blocos
catch
para tratar diferentes tipos de exceções.
- É possível ter vários blocos
try {
// Código problemático
} catch (erro1) {
// Tratamento para erro1
} catch (erro2) {
// Tratamento para erro2
}
- Bloco
finally
:- Pode ser utilizado em conjunto com
try
ecatch
para definir código que será executado independentemente de ocorrerem ou não exceções.
- Pode ser utilizado em conjunto com
try {
// Código problemático
} catch (erro) {
// Tratamento de exceção
} finally {
// Código a ser executado sempre
}
Os blocos try
e catch
são fundamentais para o tratamento de exceções em JavaScript, proporcionando uma maneira estruturada de lidar com situações inesperadas e manter o controle sobre o fluxo de execução mesmo quando ocorrem erros.