Semana 4: JavaScript Assíncrono

Promises, APIs, Web APIs e Programação Assíncrona

🚀 Objetivo: Dominar programação assíncrona e integração com APIs modernas

📊 Seu Progresso

0% concluído

1

Nível Básico

Promises, async/await e Timers

🤝 Promises

Promises são como "promessas" no JavaScript. Elas representam algo que vai acontecer no futuro - pode dar certo (resolve) ou dar errado (reject)!

📝 Exemplo Prático:

// Criando uma Promise simples
function fazerPedido(item) {
    return new Promise((resolve, reject) => {
        console.log(`🍕 Fazendo pedido de ${item}...`);
        
        // Simular tempo de preparo (2 segundos)
        setTimeout(() => {
            const sucesso = Math.random() > 0.3; // 70% de chance de sucesso
            
            if (sucesso) {
                resolve(`✅ ${item} está pronto!`);
            } else {
                reject(`❌ Ops! Não conseguimos fazer ${item}`);
            }
        }, 2000);
    });
}

// Usando a Promise
fazerPedido('Pizza Margherita')
    .then(resultado => {
        console.log(resultado); // Se deu certo
    })
    .catch(erro => {
        console.log(erro); // Se deu errado
    })
    .finally(() => {
        console.log('🏁 Pedido finalizado!');
    });

📤 Demonstração:

🍕 Restaurante Virtual
Pronto para receber pedidos!

                    

⏳ Async/Await

Async/await é uma forma mais limpa e fácil de trabalhar com Promises. É como escrever código assíncrono de forma síncrona!

// Função para simular download
function baixarArquivo(nome, tamanho) {
    return new Promise((resolve) => {
        console.log(`📥 Iniciando download de ${nome}...`);
        
        // Simular progresso do download
        let progresso = 0;
        const intervalo = setInterval(() => {
            progresso += 20;
            console.log(`📊 ${nome}: ${progresso}%`);
            
            if (progresso >= 100) {
                clearInterval(intervalo);
                resolve(`✅ ${nome} baixado com sucesso!`);
            }
        }, 500);
    });
}

// Usando async/await
async function gerenciarDownloads() {
    try {
        console.log('🚀 Iniciando downloads...');
        
        // Aguardar primeiro download
        const arquivo1 = await baixarArquivo('documento.pdf', '2MB');
        console.log(arquivo1);
        
        // Aguardar segundo download
        const arquivo2 = await baixarArquivo('imagem.jpg', '5MB');
        console.log(arquivo2);
        
        console.log('🎉 Todos os downloads concluídos!');
        
    } catch (error) {
        console.log('❌ Erro no download:', error);
    }
}

// Executar
gerenciarDownloads();

📤 Demonstração:

📥 Gerenciador de Downloads
documento.pdf
imagem.jpg

                    

🎯 Exercício: Criando um Timer Assíncrono

Crie uma função que simula um cronômetro usando async/await:

⏰ Cronômetro
00:00

Tarefa: Complete a função do cronômetro usando async/await.

2

Nível Intermediário

Fetch API, JSON e Web Storage

🌐 Fetch API

A Fetch API permite buscar dados de serviços externos. É como pedir informações para outros sites ou serviços na internet!

// Buscando dados de uma API pública
async function buscarCEP(cep) {
    try {
        console.log(`🔍 Buscando informações do CEP: ${cep}`);
        
        // Fazer requisição para API dos Correios
        const response = await fetch(`https://viacep.com.br/ws/${cep}/json/`);
        
        // Verificar se a requisição foi bem-sucedida
        if (!response.ok) {
            throw new Error('CEP não encontrado');
        }
        
        // Converter resposta para JSON
        const dados = await response.json();
        
        // Verificar se o CEP é válido
        if (dados.erro) {
            throw new Error('CEP inválido');
        }
        
        console.log('✅ Dados encontrados:', dados);
        return dados;
        
    } catch (error) {
        console.log('❌ Erro:', error.message);
        throw error;
    }
}

// Função para exibir os dados
async function consultarCEP() {
    const cep = '01310-100'; // CEP da Av. Paulista
    
    try {
        const endereco = await buscarCEP(cep);
        
        console.log(`📍 Endereço: ${endereco.logradouro}`);
        console.log(`🏙️ Cidade: ${endereco.localidade}`);
        console.log(`🗺️ Estado: ${endereco.uf}`);
        
    } catch (error) {
        console.log('Não foi possível consultar o CEP');
    }
}

// Executar consulta
consultarCEP();

📤 Demonstração:

📮 Consulta de CEP

                    

💾 JSON e Web Storage

JSON é um formato para trocar dados, e Web Storage permite salvar informações no navegador do usuário!

// Sistema de favoritos usando localStorage
class GerenciadorFavoritos {
    constructor() {
        this.chave = 'meus-favoritos';
    }
    
    // Carregar favoritos do localStorage
    carregarFavoritos() {
        try {
            const dados = localStorage.getItem(this.chave);
            return dados ? JSON.parse(dados) : [];
        } catch (error) {
            console.log('Erro ao carregar favoritos:', error);
            return [];
        }
    }
    
    // Salvar favoritos no localStorage
    salvarFavoritos(favoritos) {
        try {
            localStorage.setItem(this.chave, JSON.stringify(favoritos));
            console.log('✅ Favoritos salvos!');
        } catch (error) {
            console.log('❌ Erro ao salvar:', error);
        }
    }
    
    // Adicionar item aos favoritos
    adicionarFavorito(item) {
        const favoritos = this.carregarFavoritos();
        
        // Verificar se já existe
        if (!favoritos.find(fav => fav.id === item.id)) {
            favoritos.push({
                id: item.id,
                nome: item.nome,
                categoria: item.categoria,
                adicionadoEm: new Date().toISOString()
            });
            
            this.salvarFavoritos(favoritos);
            console.log(`⭐ ${item.nome} adicionado aos favoritos!`);
            return true;
        } else {
            console.log(`ℹ️ ${item.nome} já está nos favoritos`);
            return false;
        }
    }
    
    // Remover item dos favoritos
    removerFavorito(id) {
        const favoritos = this.carregarFavoritos();
        const novosFavoritos = favoritos.filter(fav => fav.id !== id);
        
        this.salvarFavoritos(novosFavoritos);
        console.log('🗑️ Item removido dos favoritos');
    }
    
    // Listar todos os favoritos
    listarFavoritos() {
        const favoritos = this.carregarFavoritos();
        console.log('📋 Seus favoritos:', favoritos);
        return favoritos;
    }
}

// Usando o gerenciador
const favoritos = new GerenciadorFavoritos();

// Adicionar alguns itens
favoritos.adicionarFavorito({
    id: 1,
    nome: 'JavaScript',
    categoria: 'Linguagem'
});

favoritos.adicionarFavorito({
    id: 2,
    nome: 'React',
    categoria: 'Framework'
});

// Listar favoritos
favoritos.listarFavoritos();

📤 Demonstração:

⭐ Gerenciador de Favoritos
Seus Favoritos:

                    

🎯 Exercício: Buscador de Usuários GitHub

Crie uma função que busca informações de usuários do GitHub usando a API pública:

👤 Buscador GitHub

Tarefa: Complete a função para buscar dados do GitHub.

3

Nível Avançado

Web APIs e Service Workers

📍 Geolocation API

A Geolocation API permite acessar a localização do usuário (com permissão). É útil para apps que precisam saber onde o usuário está!

// Função para obter localização do usuário
async function obterLocalizacao() {
    return new Promise((resolve, reject) => {
        // Verificar se o navegador suporta geolocalização
        if (!navigator.geolocation) {
            reject(new Error('Geolocalização não suportada'));
            return;
        }
        
        console.log('📍 Solicitando permissão de localização...');
        
        // Opções para a geolocalização
        const opcoes = {
            enableHighAccuracy: true, // Alta precisão
            timeout: 10000,          // Timeout de 10 segundos
            maximumAge: 60000        // Cache por 1 minuto
        };
        
        navigator.geolocation.getCurrentPosition(
            (posicao) => {
                const { latitude, longitude, accuracy } = posicao.coords;
                
                console.log('✅ Localização obtida!');
                console.log(`📍 Latitude: ${latitude}`);
                console.log(`📍 Longitude: ${longitude}`);
                console.log(`🎯 Precisão: ${accuracy} metros`);
                
                resolve({
                    latitude,
                    longitude,
                    accuracy,
                    timestamp: posicao.timestamp
                });
            },
            (erro) => {
                console.log('❌ Erro ao obter localização:', erro.message);
                reject(erro);
            },
            opcoes
        );
    });
}

// Função para buscar informações sobre a localização
async function obterInfoLocalizacao(lat, lng) {
    try {
        // Usar API de geocodificação reversa (exemplo com OpenStreetMap)
        const url = `https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}`;
        
        const response = await fetch(url);
        const dados = await response.json();
        
        return {
            endereco: dados.display_name,
            cidade: dados.address?.city || dados.address?.town,
            estado: dados.address?.state,
            pais: dados.address?.country
        };
    } catch (error) {
        console.log('Erro ao buscar informações:', error);
        return null;
    }
}

// Função principal
async function mostrarLocalizacao() {
    try {
        const localizacao = await obterLocalizacao();
        const info = await obterInfoLocalizacao(
            localizacao.latitude, 
            localizacao.longitude
        );
        
        if (info) {
            console.log('🏙️ Você está em:', info.cidade);
            console.log('🗺️ Estado:', info.estado);
            console.log('🌍 País:', info.pais);
        }
        
    } catch (error) {
        console.log('Não foi possível obter sua localização');
    }
}

// Executar
mostrarLocalizacao();

📤 Demonstração:

📍 Sua Localização

                    

🔔 Notification API

A Notification API permite enviar notificações para o usuário, mesmo quando ele não está olhando para a página!

// Sistema de notificações
class GerenciadorNotificacoes {
    constructor() {
        this.permissao = Notification.permission;
    }
    
    // Solicitar permissão para notificações
    async solicitarPermissao() {
        if (!('Notification' in window)) {
            throw new Error('Notificações não suportadas');
        }
        
        if (this.permissao === 'granted') {
            console.log('✅ Permissão já concedida!');
            return true;
        }
        
        console.log('🔔 Solicitando permissão...');
        
        const resultado = await Notification.requestPermission();
        this.permissao = resultado;
        
        if (resultado === 'granted') {
            console.log('✅ Permissão concedida!');
            return true;
        } else {
            console.log('❌ Permissão negada');
            return false;
        }
    }
    
    // Enviar notificação simples
    enviarNotificacao(titulo, opcoes = {}) {
        if (this.permissao !== 'granted') {
            console.log('❌ Sem permissão para notificações');
            return;
        }
        
        const configuracao = {
            body: opcoes.mensagem || 'Nova notificação!',
            icon: opcoes.icone || '🔔',
            badge: '🔔',
            tag: opcoes.tag || 'notificacao-geral',
            requireInteraction: opcoes.persistente || false,
            ...opcoes
        };
        
        const notificacao = new Notification(titulo, configuracao);
        
        // Eventos da notificação
        notificacao.onclick = () => {
            console.log('👆 Notificação clicada!');
            window.focus();
            notificacao.close();
        };
        
        notificacao.onshow = () => {
            console.log('👁️ Notificação exibida');
        };
        
        notificacao.onclose = () => {
            console.log('❌ Notificação fechada');
        };
        
        // Fechar automaticamente após 5 segundos
        if (!configuracao.requireInteraction) {
            setTimeout(() => {
                notificacao.close();
            }, 5000);
        }
        
        return notificacao;
    }
    
    // Notificação com progresso
    notificarProgresso(titulo, progresso) {
        this.enviarNotificacao(titulo, {
            mensagem: `Progresso: ${progresso}%`,
            tag: 'progresso',
            icon: '📊'
        });
    }
    
    // Notificação de lembrete
    agendarLembrete(titulo, mensagem, segundos) {
        console.log(`⏰ Lembrete agendado para ${segundos} segundos`);
        
        setTimeout(() => {
            this.enviarNotificacao(titulo, {
                mensagem: mensagem,
                tag: 'lembrete',
                icon: '⏰',
                persistente: true
            });
        }, segundos * 1000);
    }
}

// Usando o gerenciador
const notificacoes = new GerenciadorNotificacoes();

// Exemplo de uso
async function testarNotificacoes() {
    const permissao = await notificacoes.solicitarPermissao();
    
    if (permissao) {
        notificacoes.enviarNotificacao('Olá!', {
            mensagem: 'Sistema de notificações funcionando!'
        });
        
        // Agendar lembrete
        notificacoes.agendarLembrete(
            'Lembrete',
            'Não esqueça de praticar JavaScript!',
            10
        );
    }
}

// Executar teste
testarNotificacoes();

📤 Demonstração:

🔔 Central de Notificações
Status: Não verificado
Notificações enviadas: 0

                    
💻

Console Assíncrono

Teste conceitos de programação assíncrona!

// Saída aparecerá aqui...
🏆

Desafios Finais

Teste seus conhecimentos assíncronos!

🎯 Desafio 1: Monitor de APIs

Crie um sistema que monitora múltiplas APIs e exibe o status de cada uma.

JSONPlaceholder API ⏳ Aguardando
ViaCEP API ⏳ Aguardando
GitHub API ⏳ Aguardando

🎯 Desafio 2: Sistema de Upload

Simule um sistema de upload de arquivos com progresso e notificações.