Fetch e APIs do navegador: busca de dados

Aprenda a carregar e enviar dados com fetch, exibir os resultados em uma página web e manter pequenas quantidades de dados no navegador. Você lê requisições e respostas HTTP e dados JSON, trata estados de carregamento e erro e formata datas e preços de uma API para cada leitor. Você descobre por que ocorrem erros de CORS e por que chaves de API secretas não devem ficar no código de front-end. Depois, usa localStorage, sessionStorage e recursos do navegador, como geolocalização e a área de transferência.

BásicoAula 8 de 9 do curso Curso de Programação em JavaScript

O que você vai aprender

  1. Explicar como funcionam uma requisição e uma resposta HTTP, carregar dados JSON com fetch e enviar dados a uma API com o método, os cabeçalhos e o corpo adequados.
    • Ler requisições e respostas HTTP
      Descrever as partes de uma requisição e de uma resposta HTTP, relacionar cada método HTTP à ação que ele executa e ler códigos de status e cabeçalhos nas ferramentas de desenvolvimento do navegador.
    • Carregar dados JSON com fetch
      Chamar fetch, verificar o status da resposta, ler e analisar o corpo JSON e construir URLs de requisição com parâmetros de consulta codificados corretamente.
    • Enviar dados com POST, PUT, PATCH e DELETE
      Passar um objeto de opções para fetch para enviar JSON ou dados de formulário e tratar a resposta do servidor após criar, atualizar ou excluir um registro.
  2. Transformar resultados de APIs em conteúdo de página, formatar datas e valores monetários para o leitor e manter a página clara enquanto os dados carregam, falham ou chegam fora de ordem.
    • Renderizar resultados de APIs na página
      Construir elementos de página a partir dos vetores e objetos de uma resposta JSON, inserir texto de APIs com segurança e tratar campos ausentes, resultados vazios e resultados paginados.
    • Formatar datas, números e valores monetários a partir de dados de APIs
      Converter as cadeias de caracteres de datas, marcas de tempo e quantias enviadas por APIs em texto legível para o idioma, a região e o fuso horário do leitor com os formatadores Intl.
    • Exibir estados de carregamento, erro e ausência de dados
      Acompanhar as etapas de uma requisição, mostrar ao usuário uma mensagem clara para cada etapa e recuperar-se de falhas com novas tentativas.
    • Cancelar requisições, definir limites de tempo e combinar requisições
      Cancelar requisições que não são mais necessárias, definir limites de tempo, impedir que respostas antigas substituam as mais recentes e executar várias requisições em paralelo ou em sequência.
  3. Explicar a política de mesma origem e os erros de CORS e proteger chaves de API e dados dos usuários quando uma página se comunica com outros servidores.
    • Compreender a política de mesma origem e o CORS
      Identificar a origem de uma URL, explicar por que o navegador bloqueia algumas respostas de outras origens e reconhecer como cabeçalhos CORS e requisições de verificação prévia permitem que um servidor as autorize.
    • Proteger chaves de API e dados dos usuários
      Explicar o que fazem chaves de API e tokens, por que um segredo no código de front-end é público e como enviar credenciais e tratar dados dos usuários com responsabilidade.
  4. Salvar, ler e atualizar pequenas quantidades de dados com localStorage e sessionStorage e decidir o que é razoável e seguro manter no navegador.
    • Salvar e ler dados com localStorage e sessionStorage
      Usar os métodos do armazenamento web, explicar por quanto tempo cada tipo de armazenamento dura e quem pode lê-lo e converter números, booleanos e objetos em cadeias de caracteres armazenadas e vice-versa.
    • Usar o armazenamento do navegador em uma aplicação
      Restaurar o estado salvo quando uma página carrega, armazenar respostas de APIs em cache com um prazo de expiração, manter abas sincronizadas e decidir o que não deve ser armazenado.
  5. Detectar e usar APIs do navegador que precisam de uma página segura ou da permissão do usuário, como geolocalização e a área de transferência, e oferecer aos usuários uma alternativa quando um recurso estiver indisponível.
    • Obter a localização do usuário com a API de Geolocalização
      Verificar se uma API do navegador está disponível, explicar contextos seguros e solicitações de permissão e usar a API de Geolocalização com suas opções, erros e uma alternativa.
    • Copiar texto e usar outras APIs do navegador
      Copiar texto com a API da área de transferência, reagir a mudanças de conectividade, ler parâmetros do endereço da página e seguir um método para aprender qualquer nova API do navegador.

Guia de estudo de Fetch e APIs do navegador

5 capítulos

1

Fazer requisições e ler as respostas

Uma página pode pedir dados a um servidor sem carregar uma nova página. A requisição diz qual recurso você quer e o que quer fazer com ele; a resposta informa o que aconteceu. Você acompanhará essa troca na aba Network, transformará uma resposta JSON em dados JavaScript e enviará alterações de volta ao servidor. Os pontos principais a verificar são o método, o status e a estrutura do corpo: a chegada de uma resposta, por si só, não significa que a operação foi bem-sucedida.

1.1 As partes de uma troca HTTP

Uma API web permite que um programa leia ou altere dados por meio de URLs identificadas chamadas pontos de acesso da API. O JavaScript na página é o cliente. Ele envia uma requisição HTTP; o servidor responde com uma resposta HTTP. Muitas APIs enviam texto JSON, que pode representar objetos, vetores, cadeias de caracteres, números, booleanos e null.

Ler uma requisição

Considere GET https://api.example.com/books?author=Le%20Guin&limit=5. O método é GET, o caminho /books seleciona o recurso e a cadeia de consulta contém dois parâmetros. O valor de author é “Le Guin”; %20 codifica o espaço. Um e comercial separa os parâmetros. A documentação da API explica quais nomes de parâmetros ela aceita e o que cada valor significa.

Uma requisição também pode conter cabeçalhos, que são pares de nome e valor, e um corpo, que contém os dados enviados. Accept: application/json solicita uma resposta JSON. Content-Type: application/json descreve o corpo enviado. Authorization transporta credenciais. Nomes de cabeçalhos não diferenciam maiúsculas de minúsculas, então content-type e Content-Type identificam o mesmo cabeçalho.

Escolher a ação
MétodoAção pretendidaUso típico
GETLerObter uma lista de notas
POSTCriar ou enviarAdicionar uma nota
PUTSubstituirEnviar a nota completa para substituição
PATCHAlterar parteMarcar uma nota como concluída
DELETERemoverExcluir uma nota

GET e HEAD são métodos seguros: sua finalidade é a leitura, então não use GET para um botão de exclusão. GET, PUT e DELETE são idempotentes. Repetir a mesma requisição deixa o servidor no mesmo estado pretendido que executá-la uma vez. Excluir uma nota já excluída pode retornar um status diferente, mas a nota continua ausente. Repetir um POST pode criar um segundo registro.

Interpretar a resposta

A resposta contém um código de status, cabeçalhos e geralmente um corpo. O primeiro dígito agrupa o resultado:

  • 2xx: sucesso. 200 OK geralmente contém dados, 201 Created informa uma criação e 204 No Content não tem corpo.
  • 3xx: redirecionamento. Por padrão, fetch segue redirecionamentos.
  • 4xx: um problema com a requisição ou o acesso. 400 significa requisição inválida; 401 significa credenciais ausentes ou inválidas; 403 significa que o servidor entende a requisição, mas a recusa; 404 significa que o recurso não foi encontrado; 429 significa requisições em excesso.
  • 5xx: um problema no servidor, como 500 Internal Server Error ou 503 Service Unavailable.

Uma chamada a /books/42 pode retornar 200, um tipo de conteúdo JSON e {"id":42,"title":"The Dispossessed","year":1974}. Uma chamada a /books/9999 pode retornar 404 e {"error":"Book not found"}. Ambas as chamadas receberam uma resposta. Uma falha de conexão não produz um status HTTP para o JavaScript inspecionar.

Inspecionar antes de supor

Abra as ferramentas de desenvolvimento, selecione Network e acione a operação. Inspecione o método, a URL completa, o status, os cabeçalhos, o corpo e os tempos. Compare-os com o ponto de acesso, os parâmetros obrigatórios, as credenciais, os limites de requisições por período e a resposta de exemplo da documentação. Se o servidor retornou os dados corretos, investigue o código da página; se a URL da requisição estiver errada, corrija-a antes de alterar a função de renderização.

Principais conclusões

  • Um ponto de acesso é uma URL que uma API disponibiliza para uma operação.
  • O método seleciona a ação; a URL seleciona o recurso e os parâmetros.
  • Os cabeçalhos da requisição e da resposta descrevem a troca.
  • Um 404 é uma resposta, enquanto uma falha de conexão não tem status HTTP.
  • Inspecione a aba Network e compare a troca com a documentação da API.

1.2 Carregar JSON em duas etapas assíncronas

fetch(url) envia uma requisição GET e retorna uma promessa. Seu resultado é um objeto Response, disponível quando os cabeçalhos chegam. Ler o corpo é uma operação assíncrona separada. response.json() lê esse corpo e o analisa, transformando-o em dados JavaScript.

Aguardar, verificar, ler
async function loadBook(id) {
  const response = await fetch(`https://api.example.com/books/${id}`);
  if (!response.ok) {
    throw new Error(`HTTP error ${response.status}`);
  }
  return await response.json();
}

Para loadBook(42), o primeiro await obtém a resposta. A condição rejeita um resultado HTTP malsucedido. O segundo await obtém os dados analisados do livro, como { id: 42, title: "The Dispossessed", year: 1974 }. A própria função retorna uma promessa, então quem a chama também aguarda o resultado.

response.ok é verdadeiro para status de 200 a 299. Um erro HTTP como 404 ou 500 não rejeita a promessa de fetch: um servidor respondeu. Uma falha de rede, uma troca bloqueada por CORS, uma URL de requisição inválida ou um cancelamento podem rejeitá-la. Lançar um erro para !response.ok permite que um try/catch envolvente também trate falhas HTTP.

Entender o corpo

Sem await, const data = response.json() armazena uma promessa, não o livro. Acessar data.title então resulta em undefined. Omitir await de fetch também deixa uma promessa onde o código espera um Response.

Escolha o leitor de corpo adequado para a resposta: json() para JSON, text() para texto ou blob() para dados binários. Um corpo só pode ser consumido uma vez. Armazene o resultado analisado e reutilize-o. Para inspecionar também o texto JSON bruto, leia text() uma vez e chame JSON.parse(text) nessa cadeia armazenada.

Um JSON inválido causa uma rejeição com SyntaxError. Uma página de erro em HTML frequentemente causa uma mensagem “Unexpected token '<'”. Um corpo vazio, incluindo uma resposta 204, também não pode ser analisado como JSON. Verifique primeiro o status e inspecione response.headers.get("Content-Type") quando houver dúvida sobre o formato. Um status de sucesso, por si só, não garante um corpo JSON.

Construir uma consulta com segurança
const url = new URL("https://api.example.com/search");
url.searchParams.set("q", "rock & roll");
url.searchParams.set("limit", 10);

O endereço resultante é https://api.example.com/search?q=rock+%26+roll&limit=10. O e comercial no valor é codificado como parte dele. Concatenar a entrada a "?q=" pode fazer &, # ou + assumirem seus significados em URLs e alterar a busca. Uma URL relativa segue a resolução normal de endereços: a partir de https://notes.example.org/app/index.html, fetch("data/books.json") carrega /app/data/books.json nessa origem.

Acompanhar a estrutura retornada

Para {"results":[{"title":"Dune"}],"total":1}, o primeiro título é data.results[0].title. O objeto externo não é o vetor de resultados. Use a prévia da resposta para encontrar o vetor antes de percorrê-lo.

Uma função auxiliar compartilhada getJSON(url, options) pode executar a mesma verificação de status e leitura do corpo para várias chamadas. Em uma cadeia .then(), retorne response.json() da função de retorno da resposta para que a próxima receba os dados analisados. Adicione .catch() ao final para tratar etapas rejeitadas.

Principais conclusões

  • fetch e response.json() retornam promessas separadas.
  • Verifique response.ok; um erro HTTP não faz fetch ser rejeitada.
  • Leia o corpo de uma resposta uma vez e reutilize o valor armazenado.
  • Use URL.searchParams para codificar valores de consulta.
  • Leia o JSON aninhado de acordo com sua estrutura real de objetos e vetores.
  • Uma resposta bem-sucedida ainda pode conter um corpo JSON vazio ou inválido.

1.3 Enviar uma alteração e usar o resultado do servidor

O segundo argumento de fetch configura uma requisição. Suas opções incluem method, headers, body, signal e credentials. Sem essas opções, a requisição é um GET sem corpo. Para enviar JSON, você precisa preparar tanto seu texto quanto seu tipo de conteúdo.

Enviar JSON
const response = await fetch("https://api.example.com/notes", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ title: "Shopping", text: "Rice, lentils" }),
});

JSON.stringify produz {"title":"Shopping","text":"Rice, lentils"}. O cabeçalho informa ao servidor como ler esse texto. Passar o objeto diretamente como corpo envia "[object Object]". Enviar a cadeia JSON sem o cabeçalho identifica-a como text/plain;charset=UTF-8, que muitos pontos de acesso JSON rejeitam com 400 ou 415 Unsupported Media Type.

Uma criação bem-sucedida frequentemente retorna 201 com o registro armazenado, como {"id":17,"title":"Shopping","text":"Rice, lentils"}. Use esse objeto retornado para atualizar a página: o novo id do servidor é necessário para edições e exclusão posteriores.

Substituir ou atualizar
RequisiçãoCorpoSignificado
PATCH /notes/17{"done":true}Alterar o campo fornecido
PUT /notes/17A nota completa para substituiçãoSubstituir o recurso
DELETE /notes/17Frequentemente nenhumRemover o recurso

Um corpo de PUT que omite um campo pode fazer com que esse campo seja removido ou redefinido, de acordo com a API. Use o método documentado para a alteração pretendida. PUT e PATCH podem retornar um registro atualizado com 200 ou retornar 204 sem corpo.

Trate o sucesso sem supor que sempre haverá JSON:

if (!response.ok) {
  throw new Error(`HTTP error ${response.status}`);
}
const saved = response.status === 204
  ? null
  : await response.json();

Esse padrão serve para pontos de acesso documentados para retornar JSON ou 204. Uma exclusão pode ser bem-sucedida e ainda produzir um erro de análise sintática se o código chamar json() no corpo vazio sem verificar.

Escolher o formato do corpo

new FormData(formElement) coleta campos nomeados de formulário e arquivos selecionados. Passe-o diretamente como body. Deixe o navegador definir Content-Type: multipart/form-data e seu delimitador; um cabeçalho fornecido manualmente pode omitir o delimitador necessário para separar os campos. Um corpo URLSearchParams usa application/x-www-form-urlencoded.

GET e HEAD não podem transportar um corpo por meio de fetch. Coloque termos de busca e filtros na cadeia de consulta da URL. Tentar um GET com corpo resulta em rejeição com um TypeError antes que ele possa servir como requisição de busca.

Finalizar com segurança após sucesso ou falha

Desabilite o botão de envio antes de aguardar uma requisição de criação e habilite-o novamente em finally. Caso contrário, um clique duplo pode enviar duas requisições POST e criar dois registros. Não repita automaticamente uma operação de criação cujo resultado seja incerto: uma resposta perdida não confirma se o servidor fez a alteração.

Para um status de erro, o corpo pode conter uma mensagem útil como {"error":"title is required"}. Leia-o uma vez se for JSON; capture uma falha de análise sintática e mantenha uma mensagem HTTP geral para respostas vazias ou em HTML. Mantenha disponível o texto digitado pelo usuário para que ele possa corrigir a requisição.

Principais conclusões

  • Requisições JSON precisam de JSON.stringify e de um tipo de conteúdo correspondente.
  • Use PATCH para uma alteração parcial e PUT para uma substituição completa.
  • Não analise o corpo como JSON para 204 No Content.
  • Deixe o navegador definir o cabeçalho multipart ao enviar FormData.
  • Use a resposta do servidor, incluindo o ID atribuído, para atualizar a página.
  • Impeça envios duplicados e restaure os controles em finally.
2

Transformar respostas em uma página útil

Buscar dados é apenas a primeira parte de uma interface. Os leitores precisam de resultados úteis, datas e preços legíveis e uma mensagem clara enquanto aguardam. Você construirá a exibição a partir da estrutura da resposta, impedirá que valores ausentes a interrompam e tornará visíveis o sucesso, os resultados vazios e as falhas. Você também controlará requisições sobrepostas para que uma resposta lenta não substitua resultados mais recentes e escolherá quando requisições independentes podem ser executadas juntas.

2.1 Construir a exibição a partir de dados

A renderização transforma um vetor ou objeto em elementos na página. Mantenha os dados obtidos em uma variável e passe-os para uma função de renderização. Essa separação permite ordenar ou filtrar os mesmos dados sem pedi-los novamente ao servidor.

Criar um elemento por item
function renderBooks(books, list) {
  list.replaceChildren();
  for (const book of books) {
    const item = document.createElement("li");
    item.textContent = `${book.title} (${book.year})`;
    list.append(item);
  }
}

Para [{"title":"Kindred","year":1979},{"title":"Beloved","year":1987}], isso cria dois itens de lista: “Kindred (1979)” e “Beloved (1987)”. Limpar o contêiner primeiro faz uma nova busca substituir a anterior. Sem essa etapa, as listas antiga e nova se acumulam.

Manter texto externo como texto

Use textContent para títulos, descrições e outros textos de APIs. innerHTML analisa uma cadeia como marcação. Um título que contém <img src="x" onerror="alert(1)"> pode então executar código. Isso é injeção de scripts entre sites, ou XSS. Textos de formulários e do armazenamento precisam do mesmo tratamento, pois também podem ter vindo de uma fonte não confiável.

Propriedades de elementos definem valores individuais, como img.alt = book.title. Elas não tornam automaticamente todos os tipos de valor seguros. Um link fornecido por uma API ainda precisa de uma verificação de protocolo:

try {
  const target = new URL(book.url, location.href);
  if (target.protocol === "https:" || target.protocol === "http:") {
    link.href = target.href;
  }
} catch {
  link.removeAttribute("href");
}

Esse código é executado em um link recém-criado sem um href existente. Uma URL inválida ou não permitida deixa-o sem destino. Uma URL javascript: não é uma navegação web comum. Para imagens, forneça um texto alt significativo construído a partir dos dados quando possível.

Fornecer valores padrão sem perder valores reais

Campos opcionais podem estar ausentes ou ser null. book.author?.name ?? "Unknown author" primeiro tenta obter o nome aninhado e depois fornece um valor padrão. O encadeamento opcional evita acessar uma propriedade de um autor ausente.

O operador importa: 0 || "n/a" fornece "n/a", enquanto 0 ?? "n/a" mantém 0. O operador || substitui todos os valores avaliados como falsos, incluindo zero e uma cadeia vazia; ?? substitui apenas null e undefined. Um livro com zero exemplares disponíveis precisa exibir zero.

Um vetor de resultados vazio é uma busca bem-sucedida sem correspondências. Mostre “Nenhum livro corresponde à sua busca.” para que os leitores possam distingui-la de uma página que não carregou.

Substituir uma busca, adicionar outra página

Muitas APIs retornam páginas usando page, limit, uma contagem total ou uma URL next. Com 47 resultados e 10 por página, quatro páginas completas contêm 40 registros e a quinta contém 7. Uma nova busca limpa a lista anterior; “Carregar mais” adiciona a próxima página à lista atual. Mantenha essas duas ações de exibição separadas.

Para ordenar uma cópia local com os mais recentes primeiro, use [...books].sort((a, b) => b.year - a.year) e renderize essa cópia. O espalhamento cria um novo vetor, então a ordem salva da resposta continua disponível. Inspecione a estrutura da resposta antes de selecionar o vetor: uma API paginada frequentemente o coloca dentro de data.results.

Principais conclusões

  • Renderize a partir de dados salvos para que a ordenação local não precise de uma nova requisição.
  • Insira texto não confiável com textContent.
  • Valide o protocolo de um link de API antes de atribuir seu destino.
  • Use ?. para dados aninhados ausentes e ?? quando zero precisar permanecer zero.
  • Substitua os resultados para uma nova busca; adicione resultados para outra página.

2.2 Formatar datas e quantias para as pessoas

APIs retornam valores fáceis de trocar entre programas. Os leitores precisam de datas, horários e quantias formatados para seu idioma e sua região. Mantenha o valor armazenado separado do texto usado para exibi-lo.

Ler primeiro o formato da data

"2026-03-05T14:30:00Z" identifica um instante: 14:30 UTC de 5 de março de 2026. O Z significa UTC. new Date(...) transforma-o em um Date JavaScript. Uma cadeia apenas com data, como "2026-03-05", é interpretada como meia-noite UTC; uma data e hora sem deslocamento, como "2026-03-05T14:30", é interpretada como horário local.

Uma marca de tempo Unix conta a partir de 1 de janeiro de 1970, UTC. APIs frequentemente contam segundos, mas Date recebe milissegundos. new Date(1772721000 * 1000) fornece o mesmo instante de 5 de março. Omitir a multiplicação resulta em uma data em janeiro de 1970. Leia a documentação da API para identificar a unidade.

Escolher uma configuração regional e um fuso horário
const date = new Date("2026-03-05T14:30:00Z");
const dateFormat = new Intl.DateTimeFormat("en-US", {
  dateStyle: "medium",
  timeStyle: "short",
  timeZone: "UTC",
});
dateFormat.format(date);

A saída é “Mar 5, 2026, 2:30 PM”. Com en-GB, é “5 Mar 2026, 14:30”. Usar datas curtas produz “3/5/26” em en-US, “05/03/2026” em en-GB e “05.03.26” em de-DE.

A configuração regional controla a apresentação; o fuso horário controla a hora local. Sem um timeZone, o formatador usa o fuso do dispositivo. Esse instante corresponde a 9:30 da manhã em Nova York, 15:30 em Amsterdã e 11:30 da noite em Tóquio. Mantenha e envie instantes em UTC e converta-os para exibição. Uma data de calendário, como um aniversário, exige cuidado: formatar meia-noite UTC em um fuso a oeste de UTC pode mostrar o dia anterior.

Manter a moeda separada da configuração regional
const priceFormat = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "EUR",
});
priceFormat.format(1234.5);

Isso fornece €1,234.50. Para a mesma quantia, de-DE com EUR fornece 1.234,50 €; en-US com USD fornece $1,234.50; en-US com JPY fornece ¥1,235. JPY não tem subunidade monetária, então sua exibição normal não tem casas decimais. Selecionar uma configuração regional não converte moedas. Use o código de moeda fornecido com a quantia.

Algumas APIs de pagamento enviam subunidades monetárias inteiras. Com USD, 1999 centavos significam 19.99 dólares: divida por 100 antes de formatar. Não aplique esse divisor a JPY. Somar centavos inteiros resulta em 1999 + 2550 = 4549, que é formatado como $45.49. Isso evita o conhecido resultado da aritmética decimal 0.1 + 0.2, que é 0.30000000000000004.

Reutilizar o formatador

Crie um formatador uma vez para uma lista. Use undefined como sua configuração regional para selecionar o padrão do navegador; navigator.language informa a identificação do idioma preferido do navegador. Outras opções formatam 0.256 como “26%” ou 12.5 com a unidade "kilometer-per-hour" como “12.5 km/h”. new Intl.RelativeTimeFormat("en", { numeric: "auto" }).format(-1, "day") fornece “yesterday”. Datas montadas manualmente, como “03/05/2026”, continuam ambíguas entre regiões.

Principais conclusões

  • Verifique se as marcas de tempo usam segundos ou milissegundos.
  • Um fuso horário explícito torna previsível a exibição de data e hora.
  • A configuração regional controla a formatação; a moeda vem dos dados.
  • Converta as subunidades monetárias documentadas antes de formatar valores monetários.
  • Reutilize objetos formatadores Intl em uma lista.
  • Cadeias apenas com data são interpretadas como UTC e podem mudar de dia quando exibidas em outro fuso.

2.3 Mostrar o que a requisição está fazendo

Uma requisição tem um ciclo de vida visível: inativa, carregando e, em seguida, sucesso ou erro. O sucesso pode conter dados ou um resultado vazio. A página deve explicar cada estado para que os leitores saibam se devem esperar, alterar uma busca ou tentar novamente.

Manter a preparação e a limpeza juntas

Nesse tratador, getJSON verifica o status HTTP e analisa o corpo, searchUrl constrói a URL da requisição e renderResults atualiza a lista. O botão e o elemento de status já existem na página.

async function search(query) {
  button.disabled = true;
  status.textContent = "Loading…";
  try {
    const data = await getJSON(searchUrl(query));
    renderResults(data.results);
    status.textContent = data.results.length === 0 ? "No results." : "";
  } catch (error) {
    status.textContent = "Could not load results. Check your connection and try again.";
    console.error(error);
  } finally {
    button.disabled = false;
  }
}

A preparação acontece antes da espera. O caminho de sucesso renderiza os resultados e trata um vetor vazio. O bloco catch substitui a mensagem de carregamento se qualquer etapa aguardada falhar. finally restaura o botão após qualquer um dos caminhos. Se a limpeza ocorresse apenas após um await bem-sucedido, uma falha deixaria o controle desabilitado.

Explicar a causa de forma útil

Um erro HTTP tem um status que orienta a mensagem. Para 404, diga que o item não foi encontrado. Para 401, peça ao usuário que entre na conta; para 403, explique que o acesso não é permitido. Para 429, peça que aguarde. Para 5xx, explique que o serviço está com um problema e sugira tentar mais tarde.

Um TypeError de fetch pode significar uma falha de rede, uma requisição bloqueada por CORS ou uma URL inválida. O JavaScript não recebe um diagnóstico detalhado e confiável de CORS; inspecione o console do navegador e a aba Network. Um SyntaxError de json() indica JSON inválido. Cancelamentos e limites de tempo produzem erros como AbortError e TimeoutError. Mantenha os detalhes técnicos no console e ofereça aos leitores uma ação que possam entender.

Tornar as mudanças perceptíveis

Use um elemento de status existente, como <p role="status"></p>. Suas alterações são anunciadas aos leitores de tela sem mover o foco. aria-live="polite" tem uma finalidade semelhante; role="alert" é adequado para erros urgentes. Um indicador de carregamento sozinho não comunica um resultado vazio ou uma requisição malsucedida.

Um botão Tentar novamente chama a função de carregamento outra vez. Repetir requisições 400 ou 404 sem alterações geralmente repete o problema. Falhas temporárias de rede ou do serviço podem justificar uma pequena sequência limitada de novas tentativas. A espera exponencial entre tentativas aumenta a pausa, por exemplo, 1 segundo, 2 segundos e depois 4 segundos. Respeite o cabeçalho de resposta Retry-After; ele pode informar uma espera em segundos ou uma data HTTP. Evite repetir automaticamente uma requisição de criação que talvez já tenha sido bem-sucedida.

Se uma atualização falhar, mas os dados anteriores ainda forem úteis, mantenha-os visíveis com uma nota como “Exibindo resultados das 10:42. Não foi possível atualizar.” Não faça resultados antigos parecerem atuais sem avisar.

Testar os caminhos difíceis

Use as ferramentas de desenvolvimento para tornar a conexão lenta, ficar offline e requisitar um caminho inexistente. Verifique se o carregamento aparece rapidamente, se uma requisição malsucedida o substitui, se um sucesso vazio tem sua própria mensagem e se os controles voltam a ficar utilizáveis.

Principais conclusões

  • Torne visíveis o carregamento, o sucesso vazio, o sucesso com dados e os erros.
  • Coloque a limpeza compartilhada em finally.
  • Ofereça aos leitores uma ação útil e mantenha os detalhes técnicos no console.
  • Anuncie atualizações de status por meio de uma região dinâmica apropriada.
  • Limite as novas tentativas e respeite a espera solicitada pelo servidor.

2.4 Controlar requisições sobrepostas e paralelas

Requisições podem continuar depois da ação que as iniciou. Uma resposta de busca pode chegar depois que o leitor digitou outra coisa, e um serviço lento pode deixar uma página esperando por tempo demais. Controle quais resultados ainda são relevantes, além de verificar se cada requisição foi bem-sucedida.

Cancelar o trabalho que não é mais necessário

Crie um AbortController, passe seu signal para fetch e chame abort() para cancelar a requisição. O cancelamento pode interromper tanto a espera pelos cabeçalhos quanto uma leitura do corpo em andamento. A rejeição normalmente se chama "AbortError".

const controller = new AbortController();
const response = await fetch(url, { signal: controller.signal });
// A cancel button can call controller.abort().
const data = await response.json();

Envolva os dois usos de await no tratamento de erros. Se seu código cancelar intencionalmente uma busca antiga, retorne silenciosamente para esse cancelamento esperado, em vez de dizer ao usuário que o serviço falhou.

fetch não tem uma opção timeout nativa. Use um sinal como AbortSignal.timeout(5000) para limitar a requisição a 5000 ms, ou 5 segundos de tempo ativo. Antes da chegada dos cabeçalhos, ela é rejeitada com TimeoutError; depois que os cabeçalhos chegam, o sinal pode interromper a leitura do corpo.

Impedir que buscas antigas prevaleçam

Uma condição de corrida ocorre quando a ordem de conclusão altera o resultado. Um leitor digita “ca” e depois “cat”. Se “ca” retornar por último e for renderizado, a tela deixará de corresponder à entrada.

Uma abordagem cancela a requisição anterior antes de cada nova requisição. Outra atribui um número a cada chamada e permite que apenas a mais recente atualize a página:

let latest = 0;
async function search(query) {
  const request = ++latest;
  try {
    const data = await getJSON(searchUrl(query));
    if (request !== latest) return;
    renderResults(data.results);
  } catch (error) {
    if (request !== latest) return;
    showError(error);
  }
}

A verificação também impede que uma falha antiga substitua um sucesso mais recente. Aplique a mesma verificação de relevância às mensagens de carregamento e à restauração dos controles quando as chamadas se sobrepuserem.

O adiamento até cessarem os eventos reduz a quantidade de chamadas iniciadas. Cancele o temporizador anterior a cada tecla pressionada e inicie outro, por exemplo, de 300 ms. Digitar “paris” rapidamente inicia então uma requisição após a pausa. Esse adiamento economiza requisições; por si só, ele não impede que uma resposta anterior ainda em andamento chegue atrasada.

Decidir o que pode ser executado em conjunto

Requisições independentes podem começar juntas:

const [user, posts] = await Promise.all([
  getJSON(userUrl),
  getJSON(postsUrl),
]);

Para durações de 300 ms e 500 ms, as duas levam cerca de 500 ms, em vez de cerca de 800 ms em sequência. Promise.all é rejeitado assim que uma entrada é rejeitada, mas não cancela as outras operações.

Use Promise.allSettled quando resultados parciais forem úteis. Ele aguarda todas as entradas e informa cada resultado como { status: "fulfilled", value } ou { status: "rejected", reason }. Um painel pode então mostrar seções bem-sucedidas ao lado de uma que falhou.

Requisições dependentes precisam permanecer em sequência. Se uma segunda URL precisar de um ID retornado pela primeira requisição, aguarde esse ID antes de construir a segunda requisição.

Principais conclusões

  • Passe um sinal de cancelamento antes de chamar abort().
  • Capture erros tanto da busca quanto da leitura do corpo.
  • Ignore resultados e erros antigos.
  • O adiamento até cessarem os eventos reduz chamadas; uma verificação de relevância impede atualizações antigas.
  • Use Promise.all para operações independentes que precisam ser bem-sucedidas em conjunto.
  • Use Promise.allSettled quando resultados parciais forem úteis.
  • Aguarde os dados necessários antes de iniciar uma requisição dependente.
3

Ler dados de outras origens e proteger credenciais

Uma requisição pode parecer correta e ainda falhar em um navegador porque a página e a API pertencem a origens diferentes. Esse limite é controlado em conjunto pelas regras do navegador e pelos cabeçalhos de resposta do servidor. Você identificará a origem, interpretará falhas de verificação prévia e de CORS e distinguirá a permissão para ler uma resposta da permissão para executar uma ação. As credenciais exigem uma decisão separada: tudo o que é entregue a um navegador pode ser inspecionado por seu usuário.

3.1 Compreender o limite de origem do navegador

Uma origem combina o esquema, o host e a porta de uma URL. O caminho não faz parte dela. https://shop.example.com/cart e /help no mesmo site compartilham uma origem. Mudar para http://shop.example.com, https://api.example.com ou https://shop.example.com:8443 altera a origem. HTTPS normalmente usa a porta 443.

Quem permite a leitura da resposta?

A política de mesma origem limita quais recursos um script de página pode ler. Para uma busca em outra origem, o CORS permite que o servidor da API conceda acesso por meio de cabeçalhos de resposta. Uma página em https://notes.example.org que chama https://api.example.com/weather precisa da permissão da API para ler a resposta.

Access-Control-Allow-Origin: https://notes.example.org concede acesso a essa origem. O valor * permite qualquer origem para uma requisição sem credenciais. Se a resposta não tiver uma permissão correspondente, o navegador a oculta da página e fetch é rejeitada com um TypeError. O console fornece o diagnóstico de CORS; o JavaScript não recebe o motivo detalhado.

Adicionar Access-Control-Allow-Origin à requisição JavaScript não concede permissão. Ele é um cabeçalho de resposta controlado pelo servidor. Adicionar um cabeçalho personalizado à requisição pode gerar uma verificação prévia adicional.

Por que OPTIONS aparece antes de POST

Algumas requisições entre origens precisam de uma verificação prévia. O navegador envia primeiro OPTIONS, indicando o método pretendido em Access-Control-Request-Method e os nomes dos cabeçalhos que não constam da lista de segurança em Access-Control-Request-Headers. O servidor os permite com Access-Control-Allow-Methods e Access-Control-Allow-Headers, junto com a permissão para a origem.

Um GET, HEAD ou POST básico com apenas cabeçalhos permitidos pode evitar a verificação prévia. Os tipos de conteúdo permitidos incluem text/plain, application/x-www-form-urlencoded e multipart/form-data. Um POST com JSON, um cabeçalho Authorization, PUT ou DELETE exige verificação prévia, a menos que uma permissão anterior válida esteja em cache. Se a verificação prévia for recusada, a requisição real não será enviada.

Para uma requisição simples, a requisição real pode chegar ao servidor mesmo quando o navegador bloqueia posteriormente a leitura da resposta. Portanto, o CORS não substitui a autorização do servidor nem a verificação das entradas.

Cookies acrescentam outro requisito

O padrão credentials: "same-origin" envia cookies apenas para requisições da mesma origem. credentials: "include" também permite cookies elegíveis em requisições de outras origens. As regras SameSite dos cookies e as políticas para cookies de terceiros continuam em vigor.

Para permitir que o JavaScript leia uma resposta com credenciais, o servidor deve enviar Access-Control-Allow-Credentials: true e indicar explicitamente a origem da página. Access-Control-Allow-Origin: * não funciona com credenciais. Esses cabeçalhos não obrigam o navegador a enviar um cookie que seria bloqueado por outro motivo.

Diagnosticar sem ocultar o problema

mode: "no-cors" fornece uma resposta opaca com status 0 e sem corpo ou cabeçalhos legíveis. Ela não pode fornecer JSON a uma página. Uma requisição que funciona em curl também não comprova a permissão de CORS no navegador: clientes de terminal não aplicam essa política do navegador.

Inspecione o console e a aba Network. Verifique se a verificação prévia falhou ou se faltou permissão na resposta final. Corrija a configuração de resposta da API ou encaminhe a chamada pelo seu próprio servidor. Durante o desenvolvimento, sirva páginas de um servidor local: páginas file:// costumam ter origens opacas. Um servidor local ainda precisa de permissão de CORS ao chamar outra origem.

Principais conclusões

  • Uma origem consiste em esquema, host e porta.
  • Os cabeçalhos de resposta do servidor concedem permissão de leitura entre origens.
  • A verificação prévia verifica o método e os cabeçalhos propostos antes da requisição real.
  • O CORS pode ocultar uma resposta depois que uma requisição simples já foi processada.
  • Respostas com credenciais exigem uma origem explícita e um cabeçalho de credenciais.
  • no-cors produz uma resposta opaca, não um JSON legível.

3.2 Manter chaves secretas fora da página

Uma chave de API identifica uma aplicação que faz chamadas para fins de uso, limites e cobrança. Um token de acesso concede acesso para um usuário ou uma sessão. Quem possui uma credencial utilizável pode agir com a autoridade dela, então decida onde ela deve ficar antes de adicioná-la a uma requisição.

Cabeçalhos protegem a localização, não o segredo do usuário

Provedores podem exigir Authorization: Bearer <token>, X-API-Key: <key> ou um parâmetro de consulta como api_key. Siga a documentação da API. Um cabeçalho evita colocar a credencial em uma URL completa que pode entrar em registros e ferramentas de análise. Um cabeçalho Authorization ou personalizado em uma chamada de outra origem normalmente provoca uma verificação prévia.

Um cabeçalho continua visível nas ferramentas de desenvolvimento. Visitantes podem inspecionar o JavaScript que baixam e as requisições que ele envia. Minificar o código ou ocultar um valor atrás de uma variável não o torna secreto.

Acompanhar a chave em uma requisição de previsão do tempo

Suponha que o código do navegador chame https://api.weather.example/v1/current?city=Lima&key=sk_live_4f9a2c. Qualquer pessoa que abrir a aba Network pode copiar a chave e usar a cota da conta. Mover esse valor para uma variável de ambiente usada na geração da versão de distribuição não ajuda se a geração inseri-lo no JavaScript entregue à página.

Um segredo mantido no servidor muda o caminho:

  1. A página chama seu próprio site em /api/weather?city=Lima.
  2. O servidor desse site adiciona o segredo e entra em contato com o provedor de previsão do tempo.
  3. O servidor retorna os dados de previsão do tempo à página, mantendo o segredo fora da resposta.

O servidor ainda precisa controlar o acesso e o uso de seu ponto de acesso. Manter o segredo do provedor em um servidor não torna inofensivo o uso público ilimitado.

Alguns provedores emitem chaves para navegador destinadas a ser públicas. Aplique as restrições de domínio do provedor, limite as APIs permitidas e defina cotas de uso. Use uma chave dessa maneira apenas quando seu projeto documentado permitir; uma chave secreta de servidor não se torna uma chave para navegador ao receber uma restrição de domínio.

Responder à exposição

Mantenha arquivos de credenciais fora do controle de versão, por exemplo, listando .env em .gitignore. Isso impede que o arquivo seja incluído em um commit; não impede que a geração do front-end publique um valor incorporado ao código. Se uma chave for exposta, revogue-a e emita uma substituta. Removê-la do commit mais recente deixa o histórico anterior e quaisquer cópias intactos.

Proteger a troca e reduzir o desperdício

Use HTTPS para chamadas de API para que dados e credenciais sejam criptografados em trânsito. Uma chamada fetch de uma página HTTPS para uma API HTTP é bloqueada como conteúdo misto. A criptografia não impede que a pessoa que usa o navegador veja sua própria requisição.

Um limite de requisições por período restringe o uso, por exemplo, a 60 requisições por minuto. Chamadas acima do limite podem retornar 429 Too Many Requests. Armazene resultados adequados em cache, adie a busca até cessar a digitação e evite chamadas duplicadas. Se o servidor fornecer Retry-After, respeite a espera indicada em vez de repetir tentativas imediatamente.

A validação no cliente torna formulários mais fáceis de usar, mas qualquer pessoa pode chamar um ponto de acesso sem seu formulário. O próprio servidor deve validar requisições e autorizar ações. Ao exibir sua resposta, continue tratando cadeias de caracteres como texto não confiável e insira-as com textContent.

Principais conclusões

  • Código e requisições entregues ao navegador expõem quaisquer credenciais que contenham.
  • Uma chave secreta deve ficar no servidor que chama o provedor.
  • Restrinja chaves públicas para navegador por domínio, API e cota.
  • Revogue uma chave exposta; excluí-la do código atual é insuficiente.
  • HTTPS criptografa os dados em trânsito, enquanto o servidor continua validando e autorizando requisições.
4

Manter pequenas quantidades de estado no navegador

Uma configuração ou um rascunho pode sobreviver a um recarregamento sem uma nova requisição ao servidor. O armazenamento do navegador facilita isso, mas seus valores são cadeias de caracteres e sua duração depende do armazenamento escolhido. Você salvará e restaurará pequenas partes do estado, validará dados antigos antes de usá-los e dará um prazo de expiração aos resultados de APIs em cache. Você também decidirá quais dados devem ficar em outro lugar, pois o armazenamento local não é um cofre de segredos nem a única cópia segura de um trabalho importante.

4.1 Salvar cadeias de caracteres e restaurar seus tipos

O armazenamento web oferece dois armazenamentos de pares chave-valor: localStorage e sessionStorage. Eles usam os mesmos métodos, então a principal escolha é por quanto tempo os dados devem durar e quais abas devem compartilhá-los.

Escolher o tempo de vida
ArmazenamentoTempo de vidaCompartilhamento
localStorageSobrevive ao fechamento da aba e do navegador até ser removido ou limpoCompartilhado por páginas da mesma origem
sessionStorageSobrevive a recarregamentos durante a sessão da página na abaSeparado para cada aba e origem

Fechar a aba encerra seu armazenamento de sessão. Uma página recém-aberta que tenha uma página de origem pode começar com uma cópia do armazenamento de sessão dessa página, mas alterações posteriores permanecem separadas. Evite usar o armazenamento de sessão como forma de manter informações secretas de scripts.

O armazenamento segue as origens. https://app.example.com não pode compartilhar seu armazenamento com http://app.example.com. Caminhos na mesma origem o compartilham, então um prefixo como "notes-app:settings" ajuda a manter distintas as chaves de várias aplicações.

Usar os métodos de armazenamento
localStorage.setItem("notes-app:theme", "dark");
const theme = localStorage.getItem("notes-app:theme");
localStorage.removeItem("notes-app:theme");

setItem cria ou sobrescreve uma entrada. getItem retorna seu valor como cadeia de caracteres ou null se ela estiver ausente. removeItem remove uma entrada. clear() remove todas as entradas dessa área de armazenamento para a origem, o que pode afetar outros recursos no mesmo site. length e key(index) permitem inspecionar as chaves.

Use esses métodos em vez de atribuições de propriedades como localStorage.theme = "dark". Chaves como "length" ou "key" podem entrar em conflito com membros nativos quando acessadas como propriedades.

Converter valores deliberadamente

Após localStorage.setItem("count", 5), a leitura fornece "5". Adicionar 1 diretamente cria "51". Number(localStorage.getItem("count")) + 1 produz 6.

Um booleano armazenado apresenta uma armadilha semelhante. setItem("darkMode", false) armazena "false", e uma cadeia não vazia é avaliada como verdadeira. Leia com localStorage.getItem("darkMode") === "true" quando essas forem as duas cadeias esperadas no armazenamento.

Objetos e vetores precisam de JSON:

localStorage.setItem("settings", JSON.stringify({
  theme: "dark",
  fontSize: 18,
}));
const settings = JSON.parse(localStorage.getItem("settings"))
  ?? { theme: "light", fontSize: 16 };

Sem serialização, um objeto comum torna-se "[object Object]". JSON.parse(null) fornece null, então o valor padrão cobre uma entrada ausente. Uma cadeia armazenada malformada ainda precisa de try/catch, e os dados analisados precisam de uma verificação de estrutura antes do uso.

Manter o volume de trabalho pequeno

Chamadas ao armazenamento web são síncronas: o JavaScript aguarda cada uma na thread principal. Use-o para configurações, um rascunho ou uma lista curta, não para grandes coleções ou arquivos. IndexedDB fornece armazenamento assíncrono para volumes maiores de dados estruturados.

Navegadores atuais geralmente permitem cerca de 5 MiB em cada área de armazenamento web por origem. Um armazenamento cheio pode fazer setItem lançar QuotaExceededError; o acesso também pode falhar devido às configurações de privacidade do navegador. Trate a falha sem impedir o restante da aplicação de funcionar. As ferramentas de desenvolvimento mostram os armazenamentos na aba Application do Chrome e do Edge ou na aba Storage do Firefox, onde excluir entradas ajuda a testar primeiras visitas.

Principais conclusões

  • Escolha localStorage para configurações persistentes compartilhadas e sessionStorage para o estado da sessão da aba.
  • Áreas de armazenamento são separadas por origem.
  • getItem retorna uma cadeia de caracteres ou null.
  • Serialize objetos com JSON e restaure seus tipos ao ler.
  • Trate falhas de armazenamento e mantenha pequenas as gravações síncronas.

4.2 Restaurar o estado e definir a expiração dos dados em cache

Uma aplicação geralmente carrega ao iniciar e salva ao alterar. Leia uma lista salva quando a página abrir, renderize-a e salve a lista atualizada após uma edição. O armazenamento do navegador é uma cópia de conveniência: ele pode estar ausente, danificado, desatualizado ou ter sido limpo.

Validar antes de restaurar

Esta função de carregamento espera um vetor salvo de cadeias de caracteres:

function loadTodos() {
  try {
    const value = JSON.parse(localStorage.getItem("todos"));
    if (Array.isArray(value) && value.every(item => typeof item === "string")) {
      return value;
    }
  } catch {
    // Continue with an empty list if reading or parsing fails.
  }
  return [];
}

JSON.parse sozinho não comprova que o valor é um vetor ou que seus itens são adequados para a aplicação. Um JSON válido como 42 ainda tem a estrutura errada. Um valor com versão, como { version: 2, todos: [...] }, permite que o código mais recente reconheça formatos antigos e os converta ou restaure um valor padrão.

Salve a lista em memória com localStorage.setItem("todos", JSON.stringify(todos)) após cada alteração. Capture também falhas de gravação; uma página deve poder continuar funcionando mesmo quando não consegue preservar o estado para o próximo recarregamento. Um rascunho de formulário que pertence apenas a uma visita pode usar sessionStorage.

Adicionar uma marca de tempo às respostas em cache
localStorage.setItem("weather", JSON.stringify({
  savedAt: Date.now(),
  data,
}));

Em um carregamento posterior, valide primeiro a estrutura e a marca de tempo do objeto em cache. Sua idade é Date.now() - savedAt. Use-o apenas enquanto essa idade for inferior a 10 * 60 * 1000, ou 600.000 ms. Um valor salvo às 10:00:00 tem 450.000 ms de idade às 10:07:30 e pode ser usado. Às 10:12:00, tem 720.000 ms, então busque um valor atualizado. Com exatamente 600.000 ms, ele está expirado segundo essa regra.

A expiração é uma lógica da aplicação: localStorage não exclui uma entrada quando seu intervalo de validade termina. Rejeite uma marca de tempo ausente ou inválida em vez de tratar uma idade desconhecida como atual. Você pode manter dados antigos visíveis durante uma atualização malsucedida se eles estiverem identificados como antigos.

Sincronizar outras abas

Quando uma aba altera localStorage, outras abas da mesma origem recebem um evento storage. A aba que grava não recebe seu próprio evento. O evento disponibiliza key, oldValue, newValue e url.

window.addEventListener("storage", (event) => {
  if (event.key === "theme") applyTheme(event.newValue);
});

Aplique o tema imediatamente também na aba que faz a gravação. Trate null quando uma chave for removida. Um evento storage não substitui a atualização do estado da sua própria página.

Decidir o que deve ficar em outro lugar

Não coloque senhas, números de cartão de pagamento ou chaves de API secretas no armazenamento web. Scripts da origem podem lê-lo, incluindo código de terceiros e scripts injetados. Limpe dados pessoais relevantes ao sair da conta em dispositivos compartilhados. Mantenha trabalhos importantes em um servidor ou ofereça exportação, pois usuários podem limpar os dados do site e sessões privadas os descartam.

Cookies são diferentes: requisições correspondentes os enviam ao servidor, e cookies HttpOnly não podem ser lidos por scripts da página. Eles são pequenos, cerca de 4 KB cada. O armazenamento web permanece no navegador e pode ser lido por scripts. IndexedDB é adequado para volumes maiores de dados estruturados por meio de uma API assíncrona.

Principais conclusões

  • Valide os dados analisados e recorra a valores padrão quando estiverem ausentes ou danificados.
  • A validade do cache depende de uma marca de tempo e de um limite de idade definido pela aplicação.
  • O evento storage chega a outras abas da mesma origem, não à aba que gravou.
  • Mantenha segredos e dados insubstituíveis fora do armazenamento web.
5

Usar recursos de localização e da área de transferência

APIs do navegador conectam uma página a recursos como localização e área de transferência. Sua disponibilidade depende do navegador, do contexto de segurança da página e das escolhas do usuário. Você detectará um recurso antes de chamá-lo, pedirá permissão em um momento útil e tratará o sucesso ou a recusa. Uma interação completa inclui uma resposta visível e outra maneira de concluir a tarefa, como digitar uma cidade ou copiar texto selecionado com o teclado.

5.1 Solicitar uma localização com uma alternativa

A Geolocalização é uma API do navegador: um recurso fornecido pelo navegador, separado da linguagem JavaScript. Como outros recursos do dispositivo, ela pode estar indisponível ou ter seu uso recusado. Uma página de previsão do tempo deve continuar funcionando quando um leitor optar por digitar uma cidade.

Verificar o recurso e o contexto

Detecte o próprio recurso com "geolocation" in navigator. Verificar o nome de um navegador é menos confiável: versões e configurações alteram o que está disponível. A Geolocalização precisa de um contexto seguro, normalmente HTTPS; http://localhost também atende ao requisito para desenvolvimento. window.isSecureContext informa se a página atual atende ao requisito. HTTP simples no endereço de rede de outro dispositivo não é o mesmo que localhost.

Explique por que a localização é útil e solicite-a quando o leitor clicar em “Usar minha localização”. O navegador gerencia a solicitação de permissão. Uma pessoa pode permitir ou bloquear o acesso, e uma recusa anterior pode fazer uma chamada posterior falhar sem outra solicitação. O usuário altera essa decisão nas configurações do site.

Ler o resultado da função de retorno

navigator.geolocation.getCurrentPosition(success, error, options) usa funções de retorno. Em caso de sucesso, position.coords contém latitude e longitude em graus decimais e accuracy em metros. A precisão é um raio estimado de incerteza, não uma precisão decimal adicional. Em caso de falha, o código 1 significa permissão negada, 2 significa posição indisponível e 3 significa limite de tempo excedido.

As opções controlam a tentativa:

  • enableHighAccuracy: solicita maior precisão; padrão false.
  • timeout: limite de espera em milissegundos; padrão Infinity.
  • maximumAge: idade máxima de uma posição em cache aceitável; padrão 0.

Use um limite de tempo finito para que a página tenha uma forma de sair da espera. watchPosition observa atualizações ao longo do tempo e retorna um ID; passe esse ID para clearWatch quando o acompanhamento precisar parar.

Envolver funções de retorno ao usar await
function getPosition(options) {
  return new Promise((resolve, reject) => {
    navigator.geolocation.getCurrentPosition(resolve, reject, options);
  });
}

async function useLocation() {
  if (!("geolocation" in navigator)) {
    showCityInput();
    return;
  }
  try {
    const { coords } = await getPosition({ timeout: 10000 });
    const url = new URL("https://api.example.com/weather");
    url.searchParams.set("lat", coords.latitude.toFixed(2));
    url.searchParams.set("lon", coords.longitude.toFixed(2));
    await loadWeather(url);
  } catch {
    showCityInput();
  }
}

Aqui, showCityInput exibe o controle de entrada manual e loadWeather solicita e renderiza a previsão do tempo. Conecte useLocation ao botão de localização. O bloco catch cobre a falha de localização e a requisição de previsão do tempo; em ambos os casos, a entrada manual continua disponível.

Solicitar apenas a precisão útil

Uma posição com latitude 52.3676, longitude 4.9041 e precisão 35 tem um raio estimado de cerca de 35 m. Arredondar para 52.37 e 4.90 reduz a precisão enviada ao serviço de previsão do tempo. Um intervalo de latitude de 0,01° equivale a cerca de 1,1 km; a distância entre longitudes varia com a latitude. Essa precisão regional é adequada para uma previsão sem compartilhar as coordenadas mais detalhadas.

Onde a API de Permissões estiver disponível, navigator.permissions.query({ name: "geolocation" }) informa "granted", "denied" ou "prompt". Detecte e trate essa API também. Seu estado ajuda a adaptar a interface, mas não substitui o tratamento de erros da chamada de localização.

Principais conclusões

  • Detecte a Geolocalização e use um contexto seguro.
  • Solicite a localização após uma ação clara do usuário, com uma finalidade informada.
  • Latitude e longitude usam graus; a precisão usa metros.
  • Defina um limite de tempo finito e ofereça entrada manual em caso de falha.
  • Envie apenas a precisão de localização necessária ao recurso.
  • O estado da permissão não garante uma posição utilizável.

5.2 Copiar texto e aprender outra API do navegador

A API da área de transferência permite que uma página copie texto sem pedir ao leitor que o selecione primeiro. Assim como a Geolocalização, ela precisa de verificações de disponibilidade, uma ação apropriada do usuário, tratamento de erros e uma alternativa.

Copiar durante o clique

navigator.clipboard.writeText(text) retorna uma promessa. Aguarde-a antes de informar sucesso. Um contexto seguro é obrigatório, e uma operação negada pode ser rejeitada com NotAllowedError. Chame-a diretamente de um tratador de clique: Firefox e Safari exigem uma interação recente do usuário, enquanto os requisitos do Chromium também podem depender da permissão de gravação na área de transferência.

copyButton.addEventListener("click", async () => {
  try {
    if (!navigator.clipboard?.writeText) {
      throw new Error("Copy unavailable");
    }
    await navigator.clipboard.writeText(codeField.value);
    copyButton.textContent = "Copied!";
  } catch {
    codeField.focus();
    codeField.select();
    copyButton.textContent = "Copy selected text: Ctrl+C / Cmd+C";
  }
  setTimeout(() => {
    copyButton.textContent = "Copy";
  }, 2000);
});

codeField é um campo de texto ou textarea e copyButton é o botão da página. Se a cópia falhar, selecionar o texto oferece uma opção pelo teclado: Ctrl+C em muitos sistemas ou Cmd+C no macOS. O texto do botão volta a ser “Copy” após 2000 ms. Nunca mostre “Copied!” antes de a promessa ser cumprida.

A leitura usa navigator.clipboard.readText() e tem controles mais rigorosos porque uma área de transferência pode conter material privado de outras aplicações. Um navegador pode exigir permissão ou apresentar uma solicitação de colagem. A permissão para gravar não estabelece permissão para ler.

Tratar a conectividade como um indício

navigator.onLine e os eventos online e offline da janela ajudam a mostrar uma faixa de conexão. Eles não estabelecem se sua API está acessível. Um dispositivo pode ter conexão de rede enquanto o servidor da API está fora do ar ou inacessível.

window.addEventListener("offline", () => {
  status.textContent = "You are offline.";
});

Continue tratando erros em torno de fetch mesmo quando navigator.onLine for verdadeiro. Use uma região dinâmica apropriada para a mensagem de status.

Ler uma busca compartilhável

A API URL lê a cadeia de consulta da própria página, além de construir URLs de APIs. Em https://books.example.org/search?q=dune, new URL(location.href).searchParams.get("q") retorna "dune". Leia esse valor ao carregar para restaurar uma busca de um link compartilhado. Um parâmetro ausente retorna null, então decida o que a tela inicial deve mostrar nesse caso.

Usar um método de aprendizado

Para outra API do navegador, leia sua sintaxe, regras de contexto seguro e permissão, tabela de compatibilidade e status Baseline na MDN. Depois, detecte o recurso, chame-o a partir de uma ação do usuário quando necessário, trate sua promessa ou funções de retorno e ofereça uma alternativa quando ele estiver ausente ou a permissão for negada.

A API de Notificações exibe notificações do sistema após a permissão; a API de Compartilhamento Web abre um menu de compartilhamento do dispositivo onde há suporte; Canvas desenha gráficos; APIs de mídia controlam áudio e vídeo. Uma API de mapas de terceiros pode adicionar uma biblioteca e uma chave do provedor. Suas credenciais seguem as mesmas regras de chaves secretas de qualquer outro serviço. Testar um navegador em localhost não comprova que outro dispositivo ou navegador tenha o mesmo suporte e contexto.

Principais conclusões

  • Aguarde writeText antes de informar que a cópia foi bem-sucedida.
  • Mantenha uma alternativa de cópia pelo teclado quando o acesso à área de transferência falhar.
  • A leitura da área de transferência tem regras de permissão separadas e mais rigorosas.
  • O estado online não comprova que a API esteja acessível.
  • Use parâmetros de URL para restaurar uma busca compartilhável.
  • Verifique a compatibilidade, detecte recursos e trate recusas para cada API do navegador.

Exercícios resolvidos de Fetch e APIs do navegador

5 Lições Interativas

1

Construir e atualizar uma lista de leitura

14 passos
Acompanhar uma requisição desde sua URL até sua resposta JSON, depois enviar um novo registro e tratar o resultado do servidor.
  1. 1
    IntroduçãoAcompanhar uma troca

    Uma página de lista de leitura precisa carregar livros e adicionar uma nota sobre um deles. A página é o cliente; a API é o servidor. Cada troca tem uma requisição que descreve a ação e uma resposta que descreve seu resultado.

    Primeiro, leremos a troca, depois conectaremos as duas etapas assíncronas do carregamento de JSON e, por fim, enviaremos uma alteração. A resposta do servidor determina o que a página pode mostrar com segurança em seguida.

  2. 2
    ExemploLer o recurso e os filtros

    A página faz a requisição GET https://api.example.com/books?author=Le%20Guin&limit=5.

    GET solicita a leitura. /books identifica o recurso. A consulta filtra por autor e limita a quantidade de resultados. %20 representa o espaço em “Le Guin”. A documentação da API determina esses nomes de parâmetros; a página não pode escolher outro nome e esperar que o serviço o entenda.

  3. 3
    Ideia-chaveSeparar status de conexão

    Uma resposta pode informar 200 OK com um livro ou 404 Not Found com um erro. Ambos comprovam que um servidor respondeu. Uma falha de conexão não fornece um status HTTP à página.

    Inspecione a aba Network para ver a URL completa, o método, o status, os cabeçalhos e o corpo. Se a API retornou o JSON esperado, o próximo lugar a inspecionar é o código que o lê ou exibe.

  4. 4
    DesafioEscolher um método para uma alteração

    Uma nota já existe. A página deve alterar apenas seu campo done, preservando seu texto. Qual método HTTP é adequado para essa operação e por que GET estaria errado?

    ---reveal---

    Use PATCH para a atualização parcial. GET é um método seguro de leitura e não deve ser usado para solicitar uma alteração de dados. PUT descreveria uma substituição completa e poderia redefinir campos omitidos do corpo.

  5. 5
    ExplicaçãoAguardar a resposta

    Comece com const response = await fetch(url). Isso aguarda a chegada dos cabeçalhos da resposta e fornece um Response, não os dados analisados dos livros.

    A resposta ainda pode ser um erro HTTP. fetch é cumprida para um 404 porque existe uma resposta. Verifique response.ok antes de tratar a operação como bem-sucedida; ele é verdadeiro para códigos de status de 200 a 299.

  6. 6
    ExemploVerificar e ler o corpo

    Continue dentro da função assíncrona:

    if (!response.ok) {
      throw new Error(`HTTP error ${response.status}`);
    }
    const data = await response.json();
    

    A segunda espera lê e analisa o corpo. Agora data é um valor JavaScript. Um try/catch externo pode tratar tanto o erro de status lançado aqui quanto falhas na busca ou na análise do corpo.

  7. 7
    ExemploEncontrar o vetor aninhado

    Suponha que o corpo seja {"results":[{"title":"Dune"}],"total":1}.

    A primeira etapa, data.results, acessa o vetor. [0] acessa seu primeiro objeto. .title fornece "Dune". Uma função de renderização deve receber data.results, não o objeto externo inteiro. A prévia da resposta na aba Network é útil quando a estrutura da API difere do que a página esperava.

  8. 8
    DesafioDiagnosticar o valor ausente

    O código usa const data = response.json() e depois tenta acessar data.results[0]. O corpo é realmente um JSON válido com um vetor results. O que está faltando?

    ---reveal---

    Aguarde o corpo: const data = await response.json(). Sem essa espera, data é uma promessa e não tem uma propriedade results. O primeiro await fetch(...) não aguardou também a análise do JSON.

  9. 9
    DicaPreservar a pontuação em uma busca

    Construa parâmetros de consulta por meio da API URL:

    const url = new URL("https://api.example.com/search");
    url.searchParams.set("q", "rock & roll");
    

    O valor torna-se rock+%26+roll. O e comercial permanece dentro da expressão de busca em vez de dividir a consulta. Reutilize a resposta analisada após o carregamento: chamar um segundo leitor de corpo na mesma resposta falha porque o corpo foi consumido.

  10. 10
    ExemploPreparar um envio JSON

    Para criar uma nota, serialize os campos e indique seu formato:

    const response = await fetch("https://api.example.com/notes", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ title: "Read", done: false }),
    });
    

    O método solicita a criação, o cabeçalho declara JSON e o corpo contém texto JSON em vez de um objeto comum.

  11. 11
    ConexãoUsar o registro armazenado

    O servidor pode retornar 201 Created com {"id":31,"title":"Read","done":false}. Adicione esse registro retornado ao estado da página. Seu ID permite que uma ação posterior chame /notes/31.

    Para um formulário com arquivos, passe FormData em vez de JSON e deixe o navegador definir seu delimitador multipart. Uma requisição GET não pode transportar um corpo por meio de fetch; campos de busca devem ficar na cadeia de consulta.

  12. 12
    DesafioTratar um sucesso sem corpo

    Excluir uma nota salva retorna 204. O código verifica response.ok, depois chama response.json() e mostra um erro. A exclusão necessariamente falhou e o que deve mudar?

    ---reveal---

    Não: 204 informa uma conclusão bem-sucedida sem corpo. Não analise JSON para esse status e atualize a página após a verificação do status. A falha de análise veio da tentativa de ler conteúdo vazio, não de uma evidência de que a exclusão falhou.

  13. 13
    DesafioRevisar um fluxo completo de envio

    Um botão de salvar pode ser clicado duas vezes enquanto um POST está em andamento. Uma resposta bem-sucedida fornece um novo ID. Cite os dois comportamentos da página que impedem uma duplicação acidental e preservam esse ID.

    ---reveal---

    Desabilite o botão durante a requisição e restaure-o em finally. Em caso de sucesso, atualize a partir do registro retornado, incluindo seu ID. O botão impede cliques repetidos; o resultado do servidor fornece valores que não existiam nos dados enviados.

  14. 14
    RecapitulaçãoVerificar a troca em cada etapa

    Quando uma requisição não se comportar como esperado, inspecione a operação em ordem: a URL e o método documentados, o status real, o leitor de corpo escolhido e a estrutura dos dados entregues à página.

    Para uma gravação, verifique também o tipo de conteúdo e o corpo serializado. Um sucesso sem conteúdo não precisa de um leitor JSON. Uma resposta de criação deve fornecer o registro salvo usado para a próxima edição ou exclusão.

2

Construir uma página de busca que permanece atualizada

18 passos
Renderizar uma lista, formatar um preço e uma data e manter correto o estado das requisições durante buscas lentas, malsucedidas e sobrepostas.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoManter a tela associada à busca
  2. 2
    ExemploSubstituir a lista anterior
  3. 3
    Ideia-chaveDistinguir zero de dados ausentes
  4. 4
    DesafioTratar texto e links externos
  5. 5
    ExemploLer a unidade de tempo
  6. 6
    ExplicaçãoEscolher o fuso de exibição
  7. 7
    ExemploFormatar subunidades monetárias documentadas
  8. 8
    DesafioSeparar configuração regional de valor
  9. 9
    ExplicaçãoComeçar com uma espera visível
  10. 10
    ExemploFinalizar todos os caminhos
  11. 11
    DesafioReconhecer uma busca vazia bem-sucedida
  12. 12
    DicaAguardar antes de uma nova tentativa por falha temporária
  13. 13
    ExemploObservar a ordem de conclusão
  14. 14
    ExemploCancelar uma requisição antiga
  15. 15
    ConexãoReduzir chamadas durante a digitação
  16. 16
    DesafioEscolher sucesso parcial
  17. 17
    DesafioProteger toda a interação atual
  18. 18
    RecapitulaçãoTestar a interface com respostas imperfeitas
3

Diagnosticar uma chamada de API de outra origem

10 passos
Acompanhar a permissão de leitura do navegador separadamente da autorização do servidor e da proteção de uma chave do provedor.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoSeparar duas questões de permissão
  2. 2
    ExemploComparar as origens completas
  3. 3
    ExplicaçãoLer a permissão do servidor
  4. 4
    ExemploAcompanhar primeiro a verificação prévia
  5. 5
    DesafioExplicar um sucesso apenas no terminal
  6. 6
    ExemploEncontrar a chave exposta
  7. 7
    ConexãoMover o limite do segredo
  8. 8
    DesafioDistinguir transporte de segredo
  9. 9
    DesafioVerificar cookies e respostas legíveis
  10. 10
    RecapitulaçãoDiagnosticar o limite que falhou
4

Restaurar uma lista salva sem interromper a página

12 passos
Escolher o tempo de vida do armazenamento, preservar tipos de dados, validar dados restaurados e aplicar uma regra de validade ao cache.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoManter uma cópia local de conveniência
  2. 2
    ExplicaçãoEscolher o que deve permanecer
  3. 3
    ExemploPreservar um vetor como texto
  4. 4
    DesafioRestaurar o tipo pretendido
  5. 5
    DicaTratar uma gravação que não cabe
  6. 6
    ExemploVerificar mais do que a sintaxe JSON
  7. 7
    ExemploAdicionar um horário ao cache
  8. 8
    DesafioCalcular qual cache está válido
  9. 9
    ConexãoAcompanhar um tema entre abas
  10. 10
    Ideia-chaveProteger dados importantes
  11. 11
    DesafioRecuperar-se de um formato salvo antigo
  12. 12
    RecapitulaçãoTestar uma primeira visita e uma visita de retorno
5

Adicionar botões úteis de localização e cópia

13 passos
Construir interações que consideram permissões, com detecção de recursos, respostas claras e alternativas manuais.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoTornar a ação compreensível
  2. 2
    ExplicaçãoVerificar o contexto e o recurso
  3. 3
    DicaSolicitar quando o recurso for útil
  4. 4
    ExemploDefinir uma espera finita
  5. 5
    ExemploLer apenas a precisão útil
  6. 6
    DesafioRecuperar-se de uma recusa
  7. 7
    ExemploGravar durante o clique
  8. 8
    Ideia-chaveAguardar antes de informar a cópia
  9. 9
    DesafioTratar um sinal de conexão como indício
  10. 10
    ConexãoRestaurar uma busca a partir de seu link
  11. 11
    DicaVerificar outro recurso do navegador
  12. 12
    DesafioRevisar os dois botões juntos
  13. 13
    RecapitulaçãoTestar também as escolhas da pessoa

Questões de Fetch e APIs do navegador

40 Questões de Prática em 4 conjuntos

Conjunto 1: Depurar requisições, armazenamento e permissões10 Questões de Prática

Questão 1 de 10

Um serviço documenta PUT /profiles/29 como substituição do perfil. O que a idempotência implica quando a mesma requisição completa é enviada duas vezes?
  1. As duas respostas devem conter exatamente o mesmo status e cabeçalhos.
  2. A segunda requisição deve ser rejeitada antes de chegar ao serviço.
  3. O servidor deve criar um novo perfil para cada requisição idêntica.
  4. O perfil armazenado pretendido é o mesmo que após uma requisição.
Mostrar respostaOcultar resposta
Resposta: D
A idempotência diz respeito ao efeito pretendido no estado do servidor, então repetir essa substituição deixa o mesmo perfil que uma substituição. Ela não promete respostas idênticas nem impede que a segunda requisição chegue ao servidor. Criar um registro separado a cada repetição não corresponderia à ação de substituição documentada.

Questão 2 de 10

Uma requisição de criação excede o limite de tempo depois que o servidor pode tê-la recebido. A página tenta novamente de imediato, renderiza apenas os campos enviados e depois envia uma edição para um ID indefinido. Qual projeto deve substituir essa sequência?
  1. Impedir repetições, resolver criações incertas e guardar IDs retornados.
  2. Repetir após limites de tempo, manter campos enviados e derivar IDs da ordem da lista.
  3. Impedir cliques, repetir após cada limite de tempo e manter apenas campos enviados.
  4. Permitir repetições, descartar IDs retornados e usar a URL de criação para edições.
Mostrar respostaOcultar resposta
Resposta: A
Um POST que excedeu o limite de tempo pode já ter criado um registro, então evite duplicatas e esclareça o resultado antes de repeti-lo. Quando a criação for confirmada, guarde o ID retornado pelo servidor para edições posteriores. Desabilitar cliques duplos, por si só, não torna segura uma nova tentativa após o limite de tempo, e os campos enviados não podem fornecer um novo ID do servidor.

Questão 3 de 10

Uma API de eventos documenta sua marca de tempo em segundos. Uma página a passa diretamente para new Date e mostra janeiro de 1970. Qual conversão deve preceder a formatação da data?
  1. Dividir a marca de tempo por 1000.
  2. Adicionar o deslocamento UTC do leitor.
  3. Multiplicar a marca de tempo por 1000.
  4. Substituir a configuração regional do formatador.
Mostrar respostaOcultar resposta
Resposta: C
A API conta segundos, mas Date do JavaScript conta milissegundos, então multiplique o valor documentado por 1000. Uma configuração regional controla como uma data é escrita e não pode corrigir a unidade de tempo errada. Adicionar um deslocamento de fuso também não corrige uma marca de tempo menor por um fator de 1000.

Questão 4 de 10

Um catálogo mantém os dados de ontem após uma atualização retornar 503 com Retry-After: 12. Qual comportamento comunica o estado e permite a recuperação?
  1. Ocultar a falha e indicar que os dados antigos acabaram de ser atualizados.
  2. Indicar que os dados são antigos e aguardar pelo menos 12 segundos antes de uma nova tentativa limitada.
  3. Limpar a lista e repetir imediatamente até receber um status de sucesso.
  4. Tratar a resposta como sucesso vazio e desabilitar todas as atualizações futuras.
Mostrar respostaOcultar resposta
Resposta: B
Os dados anteriores podem continuar úteis se a página os identificar claramente como desatualizados e explicar que a atualização falhou. Retry-After: 12 solicita uma espera de doze segundos antes de outra tentativa; tentar novamente de imediato ignora essa instrução. Um 503 é uma falha do serviço, não uma evidência de que o catálogo não contém itens.

Questão 5 de 10

Uma tela de conta precisa de um perfil e do nome de sua equipe. O perfil retorna teamId. Os avisos são independentes e podem falhar sem ocultar os dados da conta. Como o trabalho deve ser organizado?
  1. Iniciar todas as requisições juntas e rejeitar toda a tela em qualquer falha.
  2. Executar a sequência de perfil e equipe em paralelo aos avisos; tratar cada resultado.
  3. Aguardar avisos, perfil e equipe em sequência, com um tratador de erros compartilhado.
  4. Iniciar os avisos após o perfil e a equipe apenas se os avisos também tiverem sucesso.
Mostrar respostaOcultar resposta
Resposta: B
A requisição da equipe depende do ID do perfil, então as duas formam uma sequência. Os avisos podem ser carregados independentemente, em paralelo a essa sequência, com resultados separados para que sua falha não oculte os dados da conta. Iniciar todas as requisições juntas deixa o ID da equipe ausente, enquanto tornar os avisos um pré-requisito acrescenta uma dependência sem relação.

Questão 6 de 10

Uma chave secreta de um provedor foi incluída em um commit de um repositório. Qual ação resolve o problema do uso da credencial exposta?
  1. Removê-la apenas do commit mais recente.
  2. Renomeá-la no código-fonte JavaScript.
  3. Movê-la para um cabeçalho público de requisição.
  4. Revogá-la e emitir uma substituta.
Mostrar respostaOcultar resposta
Resposta: D
Revogue a credencial exposta para que as cópias deixem de autorizar novas requisições, depois crie uma substituta e armazene-a adequadamente. Remover a chave do código atual não remove o histórico do repositório nem as cópias já feitas. Renomear uma variável ou alterar um campo da requisição não invalida a chave.

Questão 7 de 10

Um booleano salvo é restaurado com if (localStorage.getItem("compact")). O texto armazenado é "false", mas o modo compacto é ativado. Por quê?
  1. O armazenamento web restaura booleanos com seus tipos originais.
  2. Uma chave ausente retorna a cadeia "true" por padrão.
  3. Uma cadeia não vazia é avaliada como verdadeira, mesmo quando seu texto é "false".
  4. A instrução if transforma o texto armazenado em um valor verdadeiro.
Mostrar respostaOcultar resposta
Resposta: C
getItem retorna texto, e a cadeia não vazia "false" é avaliada como verdadeira em JavaScript. Ela não volta a ser automaticamente o booleano false. Se o formato armazenado for "true" ou "false", compare o valor explicitamente com "true" ao restaurar a configuração.

Questão 8 de 10

Duas abas da mesma origem compartilham o modo compacto como as cadeias “true” ou “false”. A aba A salva “false”, mas espera seu próprio evento storage; a aba B trata o evento com Boolean(event.newValue). Remover a chave deve desativar o modo compacto. Qual regra de atualização trata os três casos?
  1. Aplicar alterações na aba que grava e nos ouvintes; ativar apenas para a cadeia “true”.
  2. Depender de eventos nas duas abas; ativar para toda cadeia armazenada não vazia.
  3. Aplicar alterações apenas na aba que grava; manter o modo anterior nas outras abas.
  4. Recarregar a aba que grava; usar Boolean nos valores do evento e manter o modo após a remoção.
Mostrar respostaOcultar resposta
Resposta: A
A aba que grava deve atualizar diretamente, pois não recebe um evento storage por sua própria alteração. As outras abas tratam o evento, e comparar o valor com “true” mantém tanto “false” quanto null no estado desativado. A conversão booleana ativaria incorretamente o modo compacto para a cadeia não vazia “false”.

Questão 9 de 10

Um resultado de localização tem latitude -12.0464, longitude -77.0428 e precisão 80. O que 80 descreve?
  1. Uma estimativa de posição a 80 metros acima do nível do mar.
  2. Uma chance de 80 por cento de que a localização seja exata.
  3. Uma garantia de que o dispositivo esteja a até 80 metros.
  4. Um raio estimado de incerteza horizontal de 80 metros.
Mostrar respostaOcultar resposta
Resposta: D
A precisão descreve a incerteza estimada da posição horizontal em metros. Ela não é outra coordenada, uma marca de tempo ou uma distância exata garantida em relação ao ponto informado. A latitude e a longitude fornecem a posição estimada; o valor de precisão descreve o grau de proximidade com que essa estimativa deve localizar o dispositivo.

Questão 10 de 10

Uma página em https://recipes.example.org/search?q=green+tea lê new URL(location.href).searchParams.get("q"). Qual valor ela obtém?
  1. "green+tea"
  2. "q=green+tea"
  3. "green tea"
  4. null
Mostrar respostaOcultar resposta
Resposta: C
searchParams.get("q") obtém e decodifica o valor do parâmetro de consulta indicado, então o sinal de adição torna-se um espaço em "green tea". Ele não retorna o nome do parâmetro nem a consulta codificada bruta. Um parâmetro ausente retornaria null, mas q está presente nesse endereço.
Conjunto 2: Requisições, resultados e recursos do navegador10 Questões de Prática

Salve esta aula para ver todas as respostas e praticar cada conjunto.

Questão 1 de 10

Uma API documenta amount: 3785, currency: "USD" como subunidades monetárias inteiras. Qual número deve ser passado ao formatador de moeda?
  1. 3785
  2. 37.85
  3. 378.5
  4. 0.3785
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

Uma resposta tem status 403. O que esse status informa à página?
  1. O servidor não conseguiu receber a requisição.
  2. O servidor precisa redirecionar a URL do recurso.
  3. O servidor entendeu a requisição, mas a recusou.
  4. O servidor aceitou a requisição com um corpo vazio.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

Uma API retorna 200 com {"items":[{"name":"Cedar"}]}. Qual atribuição armazena o nome do primeiro item após const response = await fetch(url)?
  1. const name = (await response.json()).items[0].name;
  2. const name = response.json().items[0].name;
  3. const name = (await response.json())[0].items.name;
  4. const name = (await response.text()).items[0].name;
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

Um ponto de acesso aceita um corpo JSON. Qual valor body deve receber ao enviar { label: "Read" }?
  1. JSON.parse({ label: "Read" })
  2. String({ label: "Read" })
  3. { label: "Read" }.toString()
  4. JSON.stringify({ label: "Read" })
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

Uma API retorna { remaining: 0, owner: null }. Como a página pode exibir a quantidade restante e usar "Unknown" para o nome ausente do responsável?
  1. data.remaining || "n/a"; data.owner?.name ?? "Unknown";
  2. data.remaining ?? "n/a"; data.owner?.name ?? "Unknown";
  3. data.remaining ?? "n/a"; data.owner.name ?? "Unknown";
  4. data.remaining || "n/a"; data.owner.name || "Unknown";
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

Uma busca desabilita seu botão e depois aguarda uma requisição. O botão é habilitado novamente apenas após a renderização de resultados bem-sucedidos. Uma requisição malsucedida o deixa desabilitado. Onde deve ficar a instrução compartilhada que o habilita novamente?
  1. No ramo de sucesso, após limpar o status.
  2. Em um temporizador iniciado antes de verificar a resposta.
  3. Em um bloco catch que substitui toda a limpeza de sucesso.
  4. Em um bloco finally que envolve o trabalho aguardado.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Uma página está em https://studio.example.org/edit. Qual é a origem dessa página?
  1. https://studio.example.org
  2. https://studio.example.org/edit
  3. https://example.org
  4. http://studio.example.org
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

A geração de uma versão de front-end lê uma chave secreta de um provedor em um arquivo de ambiente ignorado e a envia em um cabeçalho de requisição HTTPS. Um visitante copia a chave na aba Network. Qual alteração protege uma chave substituta dos visitantes no navegador?
  1. Remover o arquivo ignorado e manter a mesma versão baixada.
  2. Gerar outra versão com uma variável menor e o mesmo cabeçalho.
  3. Revogar a chave exposta e fazer um servidor adicionar a substituta.
  4. Colocar a chave substituta no corpo e remover o cabeçalho.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Após localStorage.setItem("visits", 8), qual é o valor de localStorage.getItem("visits") + 1?
  1. "81"
  2. 9
  3. "9"
  4. 81
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Uma requisição de localização falha com o código de erro de geolocalização 1. Qual resposta ao usuário é adequada para essa falha?
  1. Explicar que a localização excedeu o tempo e repetir logo.
  2. Explicar que não existe posição e ocultar o formulário.
  3. Explicar que a localização foi negada e oferecer entrada de cidade.
  4. Explicar que a posição estava indisponível e oferecer nova tentativa.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Conjunto 3: Acompanhar os dados pela interface10 Questões de Prática

Salve esta aula para ver todas as respostas e praticar cada conjunto.

Questão 1 de 10

Duas leituras independentes levam cerca de 240 ms e 680 ms. Ignorando o tempo adicional de processamento, quanto tempo deve levar a espera pelas duas por meio de Promise.all?
  1. Cerca de 920 ms.
  2. Cerca de 240 ms.
  3. Cerca de 680 ms.
  4. Cerca de 440 ms.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

Uma chamada fetch retorna um Response com status 502. O código tem um tratador catch, mas nunca verifica response.ok. Por que sua mensagem de erro HTTP pode nunca aparecer?
  1. Um erro HTTP rejeita a promessa apenas após o tratador catch retornar.
  2. Um erro HTTP cumpre fetch; o código deve verificar seu status.
  3. Uma resposta 502 fica oculta até que seu corpo JSON seja lido.
  4. Um tratador catch recebe status do servidor apenas com no-cors.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

Um ponto de acesso de exclusão documentado retorna 204 em caso de sucesso. O que a página deve fazer antes de tentar analisar JSON?
  1. Reconhecer 204 como falha e repetir a mesma exclusão.
  2. Reconhecer 204 como sucesso e analisar um objeto vazio.
  3. Reconhecer 204 como redirecionamento e buscar a mesma URL.
  4. Reconhecer 204 como sucesso e não ler o corpo.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

Uma nova busca adiciona seus itens aos resultados antigos. Um botão separado “Carregar mais” deve continuar adicionando páginas. Como o comportamento de renderização deve ser diferente?
  1. Limpar para uma nova busca; adicionar para outra página.
  2. Adicionar para uma nova busca; limpar para outra página.
  3. Limpar nas duas ações antes de adicionar seus resultados.
  4. Adicionar nas duas ações e remover apenas itens vazios.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

Uma busca por “lo” começa e, depois, uma busca por “lotus” começa. Uma conclusão antiga pode ocultar a nova mensagem de carregamento, e uma falha antiga pode substituir resultados mais recentes. O cancelamento está indisponível na função envoltória da requisição. Qual política de atualização mantém toda a tela associada à busca atual?
  1. Apenas chamadas bem-sucedidas comparam seu número antes de renderizar.
  2. Apenas chamadas malsucedidas comparam seu número antes de mostrar erros.
  3. Apenas a chamada mais recente pode atualizar resultados, erros ou carregamento.
  4. Cada chamada limpa a lista quando sua própria requisição termina.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

De outra origem, uma página envia um POST com JSON e Content-Type: application/json. Nenhuma permissão de verificação prévia está em cache. O que o navegador deve verificar antes de enviar esse POST?
  1. Uma resposta GET contendo o mesmo JSON do POST planejado.
  2. Uma resposta OPTIONS que permita a origem, o método e os cabeçalhos.
  3. Uma requisição OPTIONS contendo o cabeçalho de resposta allow-origin.
  4. Uma resposta POST que declare desativadas as regras de mesma origem.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Um formulário de várias etapas deve sobreviver a recarregamentos em sua aba, mas terminar com a sessão dessa aba. Qual escolha de armazenamento é adequada?
  1. Usar localStorage e manter a entrada até que o código a remova.
  2. Manter o progresso apenas em uma variável JavaScript em memória.
  3. Usar localStorage e limpar a entrada a cada carregamento da página.
  4. Usar sessionStorage para preservar o progresso atual da aba.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Um cache expira após 6 minutos. Ele foi salvo às 09:12:00 e lido às 09:19:30. Como a aplicação deve tratá-lo?
  1. Ele tem 450.000 ms e precisa de dados atualizados.
  2. Ele tem 75.000 ms e pode ser usado como atual.
  3. Ele tem 450.000 ms e pode ser usado como atual.
  4. Ele tem 7.500 ms e precisa de dados atualizados.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Uma aplicação de previsão do tempo funciona em http://localhost, mas seu recurso de localização está ausente quando aberta em um celular por um endereço de rede HTTP. A aplicação também para de funcionar quando usuários de computador negam a localização. Qual projeto resolve as duas falhas?
  1. Repetir a localização ao carregar e ocultar a entrada de cidade após uma recusa.
  2. Servir por HTTPS, detectar a Geolocalização e manter a entrada de cidade disponível.
  3. Verificar o nome do navegador e solicitar a localização sem limite de espera.
  4. Manter HTTP, definir alta precisão e remover verificações do estado da permissão.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Um tratador de cópia aguarda navigator.clipboard.writeText(text). Em que momento ele deve mostrar “Copiado!”?
  1. Após essa promessa ser cumprida.
  2. Assim que writeText retornar.
  3. Quando a detecção de recursos passar.
  4. Exatamente quando o usuário clicar.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Conjunto 4: Projetar recursos de API confiáveis10 Questões de Prática

Salve esta aula para ver todas as respostas e praticar cada conjunto.

Questão 1 de 10

Uma API limita uma aplicação a 80 chamadas por minuto. Requisições acima desse limite recebem 429. O que esse status significa?
  1. O registro solicitado não existe mais.
  2. Foram feitas requisições em excesso.
  3. É necessária uma substituição completa.
  4. O ponto de acesso mudou definitivamente.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

Uma busca deve enviar o valor exato “A+B & C”. Qual código define esse valor sem tratar sua pontuação como estrutura da URL?
  1. url.search = "q=" + "A+B & C";
  2. url.hash = "q=" + "A+B & C";
  3. url.searchParams.set("q", "A+B & C");
  4. url.pathname += "?q=" + "A+B & C";
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

Um registro de API tem um título contendo texto literal <b>, um link javascript: e remaining: 0. A página deve mostrar o título literalmente, permitir apenas links web comuns e preservar a contagem. Qual plano de renderização atende às três necessidades?
  1. Usar textContent, verificar URLs HTTP(S) e definir o padrão da contagem com ??.
  2. Usar innerHTML, verificar URLs HTTP(S) e definir o padrão da contagem com ??.
  3. Usar textContent, atribuir todo href e definir o padrão da contagem com ??.
  4. Usar textContent, verificar URLs HTTP(S) e definir o padrão da contagem com ||.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

Dois leitores veem o mesmo instante UTC usando Intl.DateTimeFormat com a configuração regional fixa en-US, mas sem a opção timeZone. Os horários exibidos são diferentes. O que explica a diferença?
  1. A configuração regional escolhe o deslocamento UTC de cada leitor.
  2. O Date muda o instante armazenado por dispositivo.
  3. O sufixo Z é ignorado sem timeZone.
  4. O formatador usa o fuso horário de cada dispositivo.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

Uma busca retorna JSON válido com um vetor de resultados vazio. Seu tratador mostra a mensagem genérica de erro e mantém o botão desabilitado. Qual transição de estado corresponde a esse resultado?
  1. Mostrar sucesso vazio, manter o carregamento e continuar solicitando páginas.
  2. Mostrar falha do serviço, limpar o carregamento e tentar sem limite.
  3. Mostrar sucesso vazio, limpar o carregamento e restaurar o controle.
  4. Mostrar sucesso com dados antigos e deixar o controle desabilitado.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

Um painel carrega uma conta em 400 ms e depois precisa do ID retornado para carregar uma equipe em 200 ms. Alertas independentes levam 700 ms e podem falhar sem ocultar os dados da conta. Qual organização permite esse comportamento e quanto tempo ela leva aproximadamente quando todas as leituras são bem-sucedidas?
  1. Iniciar as três juntas e rejeitar a tela em qualquer falha; cerca de 700 ms.
  2. Executar conta e depois equipe em paralelo aos alertas, tratando cada ramo; cerca de 700 ms.
  3. Executar conta, equipe e alertas em sequência com um catch compartilhado; cerca de 1300 ms.
  4. Executar conta e alertas em paralelo e iniciar a equipe após ambos; cerca de 900 ms.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Um PATCH com JSON entre origens usa credentials: "include". A verificação prévia o permite. A resposta final tem um curinga allow-origin e permite credenciais, então o JavaScript não consegue lê-la. O servidor também supõe que o CORS torna desnecessárias as verificações do usuário. Qual política de resposta e acesso corrige esse projeto?
  1. Manter o curinga, remover a permissão de credenciais e autorizar cada ação.
  2. Indicar a origem da página, manter a permissão de credenciais e confiar no CORS como autorização.
  3. Manter o curinga e a permissão de credenciais, mas autorizar cada ação.
  4. Indicar a origem da página, manter a permissão de credenciais e autorizar cada ação.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Um provedor documenta uma chave de mapas como adequada para uso público no navegador. Qual configuração limita os sites, as operações de API e o uso total permitidos para essa chave?
  1. Restringir domínios e APIs e definir cotas de uso.
  2. Restringir domínios e APIs, mas deixar o uso ilimitado.
  3. Restringir APIs e cotas, mas permitir todos os domínios.
  4. Restringir domínios e cotas, mas permitir todas as APIs.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Uma função que carrega rascunhos analisa o texto salvo e chama .map imediatamente. Alguns usuários têm o JSON válido {"version":1,"items":[]} deixado por código antigo, e outros têm texto danificado. Qual plano de restauração trata os dois casos?
  1. Capturar apenas falhas de gravação e usar todo valor analisado como vetor.
  2. Substituir JSON.parse por JSON.stringify antes de chamar .map.
  3. Capturar falhas de leitura ou análise e validar ou converter a estrutura salva.
  4. Usar ?? [] após a análise e supor que valores não nulos são vetores.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Um notebook informa navigator.onLine === true, mas uma chamada de API é rejeitada. O que a página deve concluir sobre a conectividade e tratar em seguida?
  1. A API está acessível; interpretar a rejeição apenas como JSON inválido.
  2. Uma rede foi detectada, mas a API ainda pode estar inacessível; tratar a falha da requisição.
  3. A API está inacessível; alterar para falso o indicador online do navegador.
  4. A API está acessível; tentar novamente até receber uma resposta.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Travou em uma questão sua? Ajuda com Tarefas

Termos-Chave

68 Termos-Chave, cada um com sua definição

A

Adiamento até cessarem os eventos
O adiamento até cessarem os eventos atrasa uma operação até que eventos repetidos façam uma pausa, reiniciando a espera após cada evento para que uma sequência produza menos chamadas.
O adiamento até cessarem os eventos em um campo de busca evita enviar uma requisição separada para cada tecla pressionada em uma palavra digitada rapidamente.
Alternativa de contingência
Uma alternativa de contingência é outra forma de concluir uma tarefa quando o recurso preferido não tem suporte, é recusado ou não consegue terminar.
Selecionar um campo de link para cópia pelo teclado fornece uma alternativa de contingência quando o acesso automático à área de transferência falha.
API da área de transferência
A API da área de transferência permite que uma página leia ou grave conteúdo da área de transferência do sistema de forma assíncrona, sujeita às regras de contexto seguro e acesso do navegador.
Um botão de cópia usa a API da área de transferência após um clique e aguarda antes de mostrar sua mensagem de sucesso.
API web
Uma API web disponibiliza operações que um programa chama por URLs para ler ou alterar dados mantidos por outro sistema.
Uma API web de previsão do tempo permite que uma página solicite a previsão para uma cidade sem carregar uma nova página.
Armazenamento web
O armazenamento web fornece armazenamentos síncronos de pares chave-valor no navegador para pequenas cadeias de caracteres, separados por origem e pelo tempo de vida escolhido.
O armazenamento web mantém um objeto de configurações serializado que a página restaura quando inicia novamente.
Ativação pelo usuário
A ativação pelo usuário é uma interação reconhecida pelo navegador, como um clique recente, que pode ser exigida antes de permitir um recurso restrito.
Chamar a gravação na área de transferência diretamente em um tratador de clique fornece a ativação pelo usuário quando o navegador a exige.
Atributo HttpOnly
HttpOnly é um atributo de cookie que impede o JavaScript da página de ler esse cookie, embora ele ainda possa acompanhar requisições correspondentes.
Um cookie marcado como HttpOnly difere dos dados em localStorage, que scripts da origem podem ler.

Á

Área de armazenamento localStorage
localStorage é a área persistente de armazenamento web da origem, compartilhada por suas abas e mantida após o fechamento do navegador até ser removida ou limpa.
Um tema salvo em localStorage pode ser restaurado na próxima visita e lido por outra aba da mesma origem.
Área de armazenamento sessionStorage
sessionStorage é o armazenamento web limitado a uma origem e à sessão da página em uma aba, mantendo valores entre recarregamentos durante essa sessão.
Um formulário usa sessionStorage para um progresso que deve sobreviver a um recarregamento sem se tornar um estado persistente compartilhado.

B

Baseline
Baseline é o resumo da MDN sobre a disponibilidade de recursos nos principais navegadores, usado junto com informações detalhadas de compatibilidade e requisitos.
Verificar o Baseline ajuda a planejar testes em navegadores antes que a página dependa de uma API do navegador recém-aprendida.

C

Cabeçalho
Um cabeçalho é um valor nomeado associado a uma requisição ou resposta que descreve a troca, seu conteúdo ou seus requisitos de acesso.
Um cabeçalho Content-Type informa ao programa destinatário que o corpo que o acompanha contém JSON.
Cabeçalho Retry-After
O cabeçalho Retry-After informa a um cliente quando tentar novamente, usando uma espera em segundos ou uma data HTTP em uma resposta apropriada.
Um valor Retry-After de 15 pede que a página aguarde quinze segundos antes de outra requisição.
Cache
Um cache é uma cópia salva de dados usada para evitar a repetição de trabalho ou requisições, com uma política definida pela aplicação para decidir quando ela está atualizada.
Um cache de previsão do tempo pode mostrar imediatamente uma previsão recente, enquanto uma entrada expirada provoca uma nova requisição.
Chave de API
Uma chave de API é uma credencial que identifica uma aplicação que faz chamadas para que um provedor possa controlar o acesso, contabilizar o uso e aplicar limites ou cobranças.
Uma chave de API visível no navegador pode ser copiada, então uma chave secreta do provedor deve permanecer no servidor que faz a chamada.
Coalescência nula
A coalescência nula fornece um valor alternativo com ?? apenas quando o valor à sua esquerda é null ou undefined, preservando zeros válidos.
A coalescência nula mantém uma contagem zero de uma API em vez de substituí-la pelo texto “não disponível”.
Codificação de URL
A codificação de URL representa caracteres com segurança dentro de componentes de URL para que a pontuação dos dados não seja confundida com a estrutura do endereço.
A codificação de URL mantém o e comercial no nome de uma banda dentro do valor de consulta em vez de iniciar um novo parâmetro.
Código de status
Um código de status é um valor HTTP de três dígitos que informa o resultado de uma requisição, como sucesso, recusa ou um problema no servidor.
Um código de status 201 informa à página que o servidor criou um recurso em resposta à requisição.
Coleção FormData
FormData é um objeto do navegador que coleta campos de formulário e arquivos para envio, permitindo que fetch construa um corpo de requisição multipart.
Passar FormData como corpo permite que o navegador envie a imagem selecionada junto com os campos de texto do formulário.
Compartilhamento de recursos entre origens
CORS é o mecanismo de cabeçalhos HTTP que permite a um servidor autorizar scripts de navegador em outras origens a ler suas respostas.
A API usa CORS para permitir que uma página em um site indicado leia seus dados de previsão do tempo de um host diferente.
Condição de corrida
Uma condição de corrida é um resultado que depende da ordem em que trabalhos assíncronos terminam, como uma busca antiga substituindo resultados mais recentes.
Uma verificação do número da requisição impede uma condição de corrida quando uma busca anterior mais lenta termina depois da atual.
Configuração regional
Uma configuração regional identifica convenções de idioma e formatação regional usadas para exibir valores como datas, números e valores monetários.
A configuração regional en-US escreve uma data de forma diferente de en-GB, mesmo quando ambas formatam o mesmo instante.
Conteúdo misto
O conteúdo misto ocorre quando uma página segura solicita um recurso inseguro; navegadores bloqueiam chamadas fetch HTTP feitas por páginas HTTPS.
Uma URL HTTP de previsão do tempo causa uma falha de conteúdo misto quando a própria página é carregada por HTTPS.
Contexto seguro
Um contexto seguro é um contexto do navegador considerado confiável para APIs restritas, geralmente fornecido por HTTPS ou por uma origem local adequada.
Um contexto seguro em localhost permite o desenvolvimento, enquanto um endereço de rede HTTP simples pode não atender ao requisito.
Controlador de cancelamento
Um AbortController fornece um sinal para uma operação cancelável e pode solicitar o cancelamento ao chamar seu método abort.
A busca cria um AbortController e passa seu sinal para fetch antes que uma ação posterior o cancele.
Corpo da requisição
O corpo da requisição transporta conteúdo enviado a um servidor, como um registro JSON serializado ou campos de formulário em uma requisição de criação.
O corpo da requisição contém o título e o texto de uma nota, enquanto o método especifica que ela deve ser criada.
Corpo da resposta
O corpo da resposta é o conteúdo enviado após os cabeçalhos da resposta, que pode conter JSON, texto, dados binários ou nenhum conteúdo.
A página lê o corpo da resposta uma vez e mantém o objeto resultante para renderização e filtragem.
Cota de armazenamento
Uma cota de armazenamento é um limite de dados armazenados imposto pelo navegador; exceder o espaço disponível no armazenamento web pode fazer uma gravação lançar um erro.
Uma aplicação que mantém uma lista em memória captura um erro de cota de armazenamento e continua usando essa lista mesmo quando não consegue salvá-la.

D

Delimitador multipart
Um delimitador multipart separa campos e arquivos em um corpo multipart e é identificado em seu cabeçalho de tipo de conteúdo.
O navegador fornece o delimitador multipart quando a página envia FormData sem definir Content-Type por conta própria.
Detecção de recursos
A detecção de recursos verifica se um recurso está disponível antes de o código usá-lo, permitindo que a página escolha uma opção compatível ou uma alternativa.
A detecção de recursos com "geolocation" in navigator determina se a página pode oferecer a localização do dispositivo.

E

Encadeamento opcional
O encadeamento opcional interrompe com segurança um acesso a propriedade quando o valor antes de ?. é null ou undefined, retornando undefined.
O encadeamento opcional permite que book.author?.name trate um livro cujo objeto de autor está ausente da resposta.
Erro de análise sintática
Um erro de análise sintática ocorre quando um texto não pode ser interpretado no formato esperado, como uma página HTML passada a um leitor JSON.
Um corpo 204 vazio causa um erro de análise sintática de JSON, embora o servidor tenha concluído a operação com sucesso.
Espera exponencial entre tentativas
A espera exponencial entre tentativas aumenta a pausa entre novas tentativas por um fator multiplicador, reduzindo a carga repetida durante uma falha temporária.
A espera exponencial entre tentativas pode aguardar um, dois e quatro segundos em uma sequência limitada de novas tentativas.
Estado de carregamento
Um estado de carregamento informa ao leitor que uma operação assíncrona está em andamento enquanto a página aguarda seu resultado.
O estado de carregamento mostra “Buscando…” antes de a requisição começar e é limpo quando ela termina.
Estado vazio
Um estado vazio é a interface mostrada após uma operação bem-sucedida retornar nenhum dado correspondente, distinguindo esse resultado de uma falha.
O estado vazio diz “Nenhum registro corresponde ao seu filtro” após a API retornar um vetor vazio válido.
Evento storage
Um evento storage notifica outros contextos elegíveis da mesma origem sobre uma alteração no armazenamento; quem grava em localStorage não recebe seu próprio evento.
Um evento storage atualiza o tema em outra aba enquanto a aba que grava aplica o tema diretamente.
Expiração
A expiração é a idade ou o momento após o qual uma aplicação deixa de tratar um valor salvo como atual, mesmo que esse valor permaneça no armazenamento.
Uma expiração de dez minutos faz uma aplicação comparar o horário atual com o horário salvo junto com sua resposta em cache.

F

Formatador Intl.NumberFormat
Intl.NumberFormat é um formatador JavaScript que cria cadeias legíveis de números, moedas, porcentagens ou unidades para uma configuração regional escolhida.
A página reutiliza Intl.NumberFormat para cada preço em vez de reconstruir uma cadeia monetária para cada item.
Fuso horário
Um fuso horário determina a data de calendário e a hora local usadas para exibir um instante, incluindo as regras de deslocamento aplicáveis.
Um fuso horário UTC explícito faz com que cada leitor veja o horário de um evento em UTC em vez do fuso de seu dispositivo.

G

Geolocalização
A Geolocalização é uma API do navegador que obtém uma posição estimada do dispositivo com a permissão do usuário e informa sucesso ou falha.
A Geolocalização pode fornecer coordenadas para uma previsão próxima, com entrada de cidade por digitação disponível após uma recusa.

I

Idempotência
Idempotência significa que repetir uma operação idêntica tem o mesmo efeito pretendido no estado do servidor que executá-la uma vez.
Excluir uma nota duas vezes ilustra a idempotência: a nota continua ausente mesmo que o segundo status seja diferente.
IndexedDB
IndexedDB é o banco de dados assíncrono do navegador para volumes maiores de dados estruturados e arquivos que não se ajustam bem às pequenas tarefas do armazenamento web.
Uma página com uma grande coleção estruturada pode usar IndexedDB em vez de gravá-la repetidamente como uma única cadeia de armazenamento.
Injeção de scripts entre sites
A injeção de scripts entre sites é a execução de um script não confiável em uma página, que pode ocorrer quando cadeias externas são interpretadas como HTML.
Usar textContent para títulos de APIs elimina a interpretação como HTML que pode permitir a injeção de scripts entre sites.

J

JSON
JSON é um formato de texto para dados estruturados, incluindo objetos e vetores, que precisa ser analisado antes que o código use seus valores aninhados.
A página analisa o JSON e lê o vetor dentro de sua propriedade results antes de construir itens de lista.

L

Limite de requisições por período
Um limite de requisições por período restringe quantas operações um cliente ou uma credencial pode executar em um intervalo de tempo, ajudando um serviço a controlar o uso.
Um limite de requisições de busca pode ser excedido com uma requisição por tecla pressionada, então o adiamento até cessarem os eventos reduz chamadas desnecessárias.

M

Marca de tempo Unix
Uma marca de tempo Unix mede o tempo decorrido desde 1 de janeiro de 1970, UTC; a unidade documentada pode ser segundos ou milissegundos.
Uma marca de tempo Unix em segundos precisa ser multiplicada por 1000 antes de se tornar um valor Date do JavaScript.
Método Promise.all
Promise.all combina promessas de entrada em um vetor de resultados quando todas são cumpridas e é rejeitado assim que uma promessa de entrada é rejeitada.
A página usa Promise.all para duas leituras independentes cujos resultados precisam estar disponíveis para a exibição.
Método Promise.allSettled
Promise.allSettled aguarda cada promessa de entrada e retorna um objeto de resultado para cada uma, incluindo seu sucesso ou sua falha.
Promise.allSettled permite que um painel exiba duas seções bem-sucedidas enquanto explica a falha de uma terceira.

O

Objeto Response
Um objeto Response representa os cabeçalhos e o status retornados por fetch e fornece métodos para ler o corpo da resposta.
O objeto Response tem status 200, mas a página ainda aguarda json() para obter os dados do livro.
Operação síncrona
Uma operação síncrona termina antes que a próxima instrução prossiga, então uma chamada demorada de armazenamento pode bloquear a thread principal da página.
Uma gravação grande no armazenamento web é uma operação síncrona que pode atrasar o tratamento da próxima interação do usuário.
Origem
Uma origem é a combinação de esquema, host e porta de uma URL, que o navegador usa para definir vários limites de acesso.
Dois caminhos em um mesmo host HTTPS compartilham uma origem, mas alterar esse host ou sua porta cria outra origem.

P

Paginação
A paginação divide uma coleção de resultados em grupos menores que uma API retorna separadamente, geralmente por meio de parâmetros de página ou cursor.
A paginação permite que um botão “Carregar mais” solicite o próximo grupo enquanto mantém os itens já exibidos.
Parâmetro de consulta
Um parâmetro de consulta é um valor nomeado na parte de uma URL após ?, usado por um ponto de acesso para entradas como buscas ou limites de página.
O parâmetro de consulta limit=12 pede ao ponto de acesso de busca que retorne no máximo doze resultados.
Permissão
Uma permissão é uma decisão gerenciada pelo navegador que permite ou recusa o acesso de uma página a um recurso protegido, como a localização do dispositivo.
Uma recusa de permissão lembrada pelo navegador pode fazer uma requisição de localização falhar sem exibir uma segunda solicitação.
Política de mesma origem
A política de mesma origem é um limite de segurança do navegador que restringe como um script pode ler recursos pertencentes a outra origem.
A política de mesma origem faz com que uma chamada fetch entre origens dependa da permissão de leitura por CORS do servidor da API.
Ponto de acesso da API
Um ponto de acesso da API é um endereço de API que aceita uma requisição documentada para um recurso ou operação, frequentemente usando um método HTTP específico.
O ponto de acesso de notas aceita um POST para criar uma nota e retorna o identificador do novo registro.
Precisão da localização
A precisão da localização descreve a incerteza horizontal estimada ao redor de uma posição informada, medida em metros, e não em graus.
Uma precisão da localização de 60 metros descreve o raio estimado de incerteza ao redor da posição informada.
Propriedade textContent
A propriedade textContent lê ou define o texto de um elemento sem interpretar a cadeia fornecida como marcação HTML.
Atribuir um título a textContent exibe seus sinais de menor e maior literalmente em vez de criar um elemento HTML.

R

Região dinâmica
Uma região dinâmica é uma área da página cujas alterações de conteúdo podem ser anunciadas por tecnologia assistiva sem mover o foco do teclado.
Uma região dinâmica com role="status" anuncia “Carregando…” e a mensagem posterior do resultado da busca.
Renderização
A renderização transforma dados em conteúdo visível na página, como criar um elemento de lista para cada objeto no vetor de resultados de uma API.
A renderização de uma nova busca começa limpando a lista anterior e depois adicionando os itens do resultado atual.
Requisição de verificação prévia
Uma requisição de verificação prévia é uma requisição OPTIONS enviada pelo navegador que verifica a permissão entre origens para um método e cabeçalhos de requisição pretendidos.
Um POST com JSON pode precisar de uma verificação prévia antes que o navegador envie o registro que a página quer criar.
Requisição HTTP
Uma requisição HTTP é uma mensagem de um cliente para um servidor com método, URL, cabeçalhos e, para algumas operações, um corpo.
A requisição HTTP solicita /books e inclui um parâmetro de consulta que limita a quantidade de resultados.
Resposta HTTP
Uma resposta HTTP é a resposta de um servidor a uma requisição, contendo um código de status, cabeçalhos e geralmente um corpo com dados ou um erro.
A resposta HTTP informa 404 e explica em seu corpo que o livro solicitado não foi encontrado.
Resposta opaca
Uma resposta opaca oculta detalhes de status, cabeçalhos e corpo do código da página e expõe um valor de status igual a zero.
Uma chamada fetch no-cors fornece uma resposta opaca, então a página não consegue extrair o JSON que esperava exibir.

S

Serialização
A serialização converte um valor em um formato que pode ser armazenado ou transmitido, como transformar um objeto JavaScript em texto JSON.
A serialização com JSON.stringify preserva os campos de uma nota quando são enviados como corpo de requisição JSON.
Sinal de cancelamento
Um AbortSignal conecta um cancelamento ou limite de tempo a uma operação assíncrona como fetch e à leitura de seu corpo em andamento.
Um AbortSignal de AbortSignal.timeout(4000) limita uma requisição a quatro segundos de tempo ativo.
Subunidade monetária
Uma subunidade monetária é uma subdivisão da unidade principal de uma moeda, como um centavo para USD, usada por algumas APIs para quantias inteiras.
Quando uma API documenta subunidades monetárias em USD, o inteiro 4680 representa 46.80 dólares.

T

Tempo Universal Coordenado
UTC é a referência de tempo compartilhada usada para identificar instantes entre fusos horários, representada por Z no final de uma data e hora ISO.
A API retorna um instante em UTC, e a página formata esse instante para um leitor em outro fuso horário.
Token de acesso
Um token de acesso é uma credencial que concede acesso definido para um usuário ou uma sessão, permitindo que seu portador faça requisições autorizadas.
O cabeçalho Authorization da requisição transporta um token de acesso para a operação permitida ao usuário que entrou na conta.

Sobre esta aula

Por StudeliRelatar um erro

Crie seus próprios Materiais de Estudo

Transforme suas anotações, slides e documentos em Guias de Estudo, Questões de Prática, Flashcards e mais 6 ferramentas.

Começar