Fetch y API del navegador: obtención de datos

Aprende a cargar y enviar datos con fetch, mostrar los resultados en una página web y almacenar pequeñas cantidades de datos en el navegador. Interpreta solicitudes y respuestas HTTP y datos JSON, maneja los estados de carga y de error, y da formato a fechas y precios de una API para cada lector. Descubre por qué se producen errores de CORS y por qué las claves secretas de API no deben estar en el código del cliente. Después, usa localStorage, sessionStorage y funciones del navegador como la geolocalización y el portapapeles.

PrincipianteUnidad 8 de 9 del curso Curso de Programación en JavaScript

Lo que aprenderás

  1. Explica cómo funcionan una solicitud y una respuesta HTTP, carga datos JSON con fetch y envía datos a una API con el método, las cabeceras y el cuerpo adecuados.
    • Interpreta solicitudes y respuestas HTTP
      Describe las partes de una solicitud y una respuesta HTTP, relaciona cada método HTTP con la acción que realiza e interpreta los códigos de estado y las cabeceras en las herramientas de desarrollo del navegador.
    • Carga datos JSON con fetch
      Llama a fetch, comprueba el estado de la respuesta, lee y analiza el cuerpo JSON y construye URL de solicitud con parámetros de consulta correctamente codificados.
    • Envía datos con POST, PUT, PATCH y DELETE
      Pasa un objeto de opciones a fetch para enviar JSON o datos de formulario y maneja la respuesta del servidor después de crear, actualizar o eliminar un registro.
  2. Convierte resultados de una API en contenido de la página, da formato a fechas e importes monetarios para el lector y mantén la página clara mientras los datos se cargan, falla la carga o los datos llegan fuera de orden.
    • Renderiza los resultados de una API en la página
      Construye elementos de página a partir de los arrays y objetos de una respuesta JSON, inserta de forma segura el texto de la API y maneja campos ausentes, resultados vacíos y resultados paginados.
    • Da formato a fechas, números e importes monetarios procedentes de una API
      Convierte las cadenas de fecha, marcas de tiempo e importes que envían las API en texto legible para el idioma, la región y la zona horaria del lector con los formateadores de Intl.
    • Muestra estados de carga, de error y sin datos
      Haz seguimiento de las etapas de una solicitud, muestra al usuario un mensaje claro para cada etapa y recupérate de los fallos mediante reintentos.
    • Cancela solicitudes, establece tiempos límite y combina solicitudes
      Cancela solicitudes que ya no se necesitan, establece tiempos límite, evita que las respuestas obsoletas sustituyan a las más recientes y ejecuta varias solicitudes en paralelo o en secuencia.
  3. Explica la política del mismo origen y los errores de CORS, y protege las claves de API y los datos de los usuarios cuando una página se comunica con otros servidores.
    • Comprende la política del mismo origen y CORS
      Identifica el origen de una URL, explica por qué el navegador bloquea algunas respuestas de otros orígenes y reconoce cómo las cabeceras CORS y las solicitudes de verificación previa permiten que un servidor las autorice.
    • Protege las claves de API y los datos de los usuarios
      Explica para qué sirven las claves de API y los tokens, por qué un secreto en el código del cliente es público y cómo enviar credenciales y manejar los datos de los usuarios de forma responsable.
  4. Guarda, lee y actualiza pequeñas cantidades de datos con localStorage y sessionStorage, y decide qué es razonable y seguro conservar en el navegador.
    • Guarda y lee datos con localStorage y sessionStorage
      Usa los métodos de Web Storage, explica cuánto dura cada tipo de almacenamiento y quién puede leerlo, y convierte números, booleanos y objetos a cadenas almacenadas y de nuevo a sus tipos originales.
    • Usa el almacenamiento del navegador en una aplicación
      Restaura el estado guardado cuando se carga una página, almacena respuestas de API en caché con un tiempo de caducidad, mantén las pestañas sincronizadas y decide qué no se debe almacenar.
  5. Detecta y usa API del navegador que necesitan una página segura o el permiso del usuario, como la geolocalización y el portapapeles, y ofrece a los usuarios una alternativa cuando una función no esté disponible.
    • Obtén la ubicación del usuario con la API de geolocalización
      Comprueba que una API del navegador está disponible, explica los contextos seguros y las solicitudes de permiso, y usa la API de geolocalización con sus opciones, errores y una alternativa de respaldo.
    • Copia texto y usa otras API del navegador
      Copia texto con la API del portapapeles, responde a cambios de conectividad, lee parámetros de la dirección de la página y sigue un método para aprender cualquier API nueva del navegador.

Guía de estudio de Fetch y API del navegador

5 capítulos

1

Haz solicitudes e interpreta las respuestas

Una página puede pedir datos a un servidor sin cargar una página nueva. La solicitud indica qué recurso quieres y qué quieres hacer con él; la respuesta te dice qué ha ocurrido. Seguirás ese intercambio en la pestaña Network, convertirás una respuesta JSON en datos de JavaScript y enviarás cambios al servidor. Los puntos de comprobación importantes son el método, el estado y la estructura del cuerpo: recibir una respuesta no significa por sí solo que la operación haya tenido éxito.

1.1 Las partes de un intercambio HTTP

Una API web permite que un programa lea o modifique datos mediante URL identificadas llamadas puntos de acceso. El JavaScript de la página es el cliente. Envía una solicitud HTTP; el servidor responde con una respuesta HTTP. Muchas API envían texto JSON, que puede representar objetos, arrays, cadenas de caracteres, números, booleanos y null.

Interpreta una solicitud

Considera GET https://api.example.com/books?author=Le%20Guin&limit=5. El método es GET, la ruta /books selecciona el recurso y la cadena de consulta contiene dos parámetros. El valor de author es «Le Guin»; %20 codifica el espacio. Un signo & separa los parámetros. La documentación de la API explica qué nombres de parámetros acepta y qué significa cada valor.

Una solicitud también puede llevar cabeceras, que son pares de nombre y valor, y un cuerpo, que contiene los datos enviados. Accept: application/json solicita una respuesta JSON. Content-Type: application/json describe el cuerpo que se envía. Authorization transporta credenciales. Los nombres de las cabeceras no distinguen mayúsculas de minúsculas, así que content-type y Content-Type identifican la misma cabecera.

Elige la acción
MétodoAcción previstaUso habitual
GETLeerObtener una lista de notas
POSTCrear o enviarAñadir una nota
PUTSustituirEnviar la nota completa de reemplazo
PATCHModificar una parteMarcar una nota como completada
DELETEEliminarEliminar una nota

GET y HEAD son métodos seguros: su finalidad prevista es leer, así que no uses GET para un botón de eliminación. GET, PUT y DELETE son idempotentes. Repetir la misma solicitud deja el servidor en el mismo estado previsto que ejecutarla una vez. Eliminar una nota ya eliminada puede devolver un estado distinto, pero la nota sigue ausente. Repetir un POST puede crear un segundo registro.

Interpreta la respuesta

La respuesta contiene un código de estado, cabeceras y normalmente un cuerpo. El primer dígito agrupa el resultado:

  • 2xx: éxito. 200 OK suele tener datos, 201 Created informa de una creación y 204 No Content no tiene cuerpo.
  • 3xx: redirección. De forma predeterminada, fetch sigue las redirecciones.
  • 4xx: un problema con la solicitud o el acceso. 400 significa solicitud incorrecta; 401 significa credenciales ausentes o no válidas; 403 significa que el servidor entiende la solicitud pero la rechaza; 404 significa que no se encontró; 429 significa que hay demasiadas solicitudes.
  • 5xx: un problema del servidor, como 500 Internal Server Error o 503 Service Unavailable.

Una llamada a /books/42 podría devolver 200, un tipo de contenido JSON y {"id":42,"title":"The Dispossessed","year":1974}. Una llamada a /books/9999 podría devolver 404 y {"error":"Book not found"}. Ambas llamadas recibieron una respuesta. Un fallo de conexión no produce ningún estado HTTP que JavaScript pueda examinar.

Inspecciona antes de hacer suposiciones

Abre las herramientas de desarrollo, selecciona Network y desencadena la acción. Inspecciona el método, la URL completa, el estado, las cabeceras, el cuerpo y los tiempos. Compáralos con el punto de acceso, los parámetros obligatorios, las credenciales, los límites de frecuencia y la respuesta de ejemplo de la documentación. Si el servidor devolvió los datos correctos, investiga el código de la página; si la URL de la solicitud es incorrecta, corrígela antes de modificar el código de renderizado.

Puntos clave

  • Un punto de acceso es una URL que una API expone para una operación.
  • El método selecciona la acción; la URL selecciona el recurso y los parámetros.
  • Las cabeceras de solicitud y respuesta describen el intercambio.
  • Un 404 es una respuesta, mientras que un fallo de conexión no tiene estado HTTP.
  • Inspecciona la pestaña Network y compara el intercambio con la documentación de la API.

1.2 Carga JSON en dos pasos asíncronos

fetch(url) envía una solicitud GET y devuelve una promesa. Su resultado es un objeto Response, disponible cuando llegan las cabeceras. Leer el cuerpo es una operación asíncrona independiente. response.json() lee ese cuerpo y lo analiza para convertirlo en datos de JavaScript.

Espera, comprueba y lee
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), el primer await obtiene la respuesta. La condición rechaza un resultado HTTP fallido. El segundo await obtiene el libro analizado, como { id: 42, title: "The Dispossessed", year: 1974 }. La propia función devuelve una promesa, por lo que quien la llama también espera el resultado.

response.ok es verdadero para los estados de 200 a 299. Un error HTTP como 404 o 500 no rechaza la promesa de fetch: un servidor respondió. Un fallo de red, un intercambio bloqueado por CORS, una URL de solicitud no válida o una cancelación pueden rechazarla. Lanzar un error ante !response.ok permite que un try/catch que lo rodee maneje también los fallos HTTP.

Comprende el cuerpo

Sin await, const data = response.json() almacena una promesa, no el libro. Acceder entonces a data.title da undefined. Omitir await en fetch deja igualmente una promesa donde el código espera un Response.

Elige el lector de cuerpo adecuado para la respuesta: json() para JSON, text() para texto o blob() para datos binarios. Un cuerpo solo se puede consumir una vez. Guarda el resultado analizado y reutilízalo. Para inspeccionar también el texto JSON sin procesar, lee text() una vez y después llama a JSON.parse(text) sobre esa cadena guardada.

Un JSON no válido se rechaza con un SyntaxError. Una página HTML de error suele causar un mensaje «Unexpected token '<'». Un cuerpo vacío, incluido el de una respuesta 204, tampoco se puede analizar como JSON. Comprueba primero el estado e inspecciona response.headers.get("Content-Type") cuando tengas dudas sobre el formato. Un estado de éxito por sí solo no garantiza un cuerpo JSON.

Construye una consulta de forma segura
const url = new URL("https://api.example.com/search");
url.searchParams.set("q", "rock & roll");
url.searchParams.set("limit", 10);

La dirección resultante es https://api.example.com/search?q=rock+%26+roll&limit=10. El signo & incluido se codifica como parte del valor. Unir la entrada a "?q=" puede dar a &, # o + sus significados en una URL y cambiar la búsqueda. Una URL relativa sigue la resolución normal de direcciones: desde https://notes.example.org/app/index.html, fetch("data/books.json") carga /app/data/books.json en ese origen.

Sigue la estructura devuelta

Para {"results":[{"title":"Dune"}],"total":1}, el primer título es data.results[0].title. El objeto exterior no es el array de resultados. Usa la vista previa de la respuesta para encontrar el array antes de recorrerlo.

Una función auxiliar compartida getJSON(url, options) puede realizar la misma comprobación de estado y lectura del cuerpo para muchas llamadas. En una cadena .then(), devuelve response.json() desde la función de devolución de llamada de la respuesta para que la siguiente reciba los datos analizados. Añade .catch() al final para manejar los pasos rechazados.

Puntos clave

  • fetch y response.json() devuelven promesas separadas.
  • Comprueba response.ok; un error HTTP no hace que fetch se rechace.
  • Lee el cuerpo de una respuesta una sola vez y reutiliza el valor guardado.
  • Usa URL.searchParams para codificar los valores de consulta.
  • Lee el JSON anidado según su estructura real de objetos y arrays.
  • Una respuesta correcta puede contener un cuerpo JSON vacío o no válido.

1.3 Envía un cambio y usa el resultado del servidor

El segundo argumento de fetch configura una solicitud. Sus opciones incluyen method, headers, body, signal y credentials. Sin estas opciones, la solicitud es un GET sin cuerpo. Para enviar JSON, debes preparar tanto su texto como su tipo de contenido.

Envía 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 produce {"title":"Shopping","text":"Rice, lentils"}. La cabecera indica al servidor cómo leer ese texto. Pasar el objeto directamente como cuerpo envía "[object Object]". Enviar la cadena JSON sin la cabecera la etiqueta como text/plain;charset=UTF-8, que muchos puntos de acceso JSON rechazan con 400 o 415 Unsupported Media Type.

Una creación correcta suele devolver 201 con el registro almacenado, como {"id":17,"title":"Shopping","text":"Rice, lentils"}. Usa este objeto devuelto para actualizar la página: el nuevo id del servidor es necesario para ediciones y eliminaciones posteriores.

Sustituye o actualiza
SolicitudCuerpoSignificado
PATCH /notes/17{"done":true}Modificar el campo proporcionado
PUT /notes/17La nota completa de reemplazoSustituir el recurso
DELETE /notes/17A menudo ningunoEliminar el recurso

Un cuerpo de PUT que omite un campo puede hacer que ese campo se elimine o restablezca, según la API. Usa el método documentado para el cambio previsto. PUT y PATCH pueden devolver un registro actualizado con 200 o devolver 204 sin cuerpo.

Maneja el éxito sin suponer que siempre habrá JSON a continuación:

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

Este patrón sirve para puntos de acceso documentados para devolver JSON o 204. Una eliminación puede tener éxito y aun así producir un error de análisis sintáctico si el código llama a json() sobre su cuerpo vacío sin comprobarlo.

Elige el formato del cuerpo

new FormData(formElement) recopila los campos con nombre de un formulario y los archivos seleccionados. Pásalo directamente como body. Deja que el navegador establezca Content-Type: multipart/form-data y su delimitador; una cabecera proporcionada manualmente puede omitir el delimitador necesario para separar los campos. Un cuerpo URLSearchParams usa application/x-www-form-urlencoded.

GET y HEAD no pueden llevar un cuerpo mediante fetch. Pon los términos de búsqueda y los filtros en la cadena de consulta de la URL. Intentar un GET con cuerpo se rechaza con un TypeError antes de que pueda servir como solicitud de búsqueda.

Termina de forma segura tras el éxito o el fallo

Desactiva el botón de envío antes de esperar una solicitud de creación y vuelve a activarlo en finally. De lo contrario, un doble clic puede enviar dos solicitudes POST y crear dos registros. No repitas automáticamente una operación de creación cuyo resultado sea incierto: una respuesta perdida no determina si el servidor hizo el cambio.

Para un estado de error, el cuerpo puede contener un mensaje útil como {"error":"title is required"}. Léelo una vez si es JSON; captura un fallo de análisis y conserva un mensaje HTTP general para respuestas vacías o HTML. Mantén disponible el texto introducido por el usuario para que pueda corregir la solicitud.

Puntos clave

  • Las solicitudes JSON necesitan JSON.stringify y un tipo de contenido correspondiente.
  • Usa PATCH para una modificación parcial y PUT para una sustitución completa.
  • Omite el análisis de JSON para 204 No Content.
  • Deja que el navegador establezca la cabecera multiparte al enviar FormData.
  • Usa la respuesta del servidor, incluido el ID que asignó, para actualizar la página.
  • Evita envíos duplicados y restablece los controles en finally.
2

Convierte las respuestas en una página útil

Obtener datos es solo la primera parte de una interfaz. Los lectores necesitan resultados útiles, fechas y precios legibles, y un mensaje claro mientras esperan. Construirás la presentación a partir de la estructura de la respuesta, evitarás que los valores ausentes la hagan fallar y mostrarás el éxito, los resultados vacíos y los fallos. También controlarás las solicitudes simultáneas para que una respuesta lenta no pueda sustituir resultados más recientes, y elegirás cuándo pueden ejecutarse juntas las solicitudes independientes.

2.1 Construye la presentación a partir de datos

El renderizado convierte un array o un objeto en elementos de la página. Guarda los datos obtenidos en una variable y pásalos a una función de renderizado. Esa separación permite ordenar o filtrar los mismos datos sin volver a pedirlos al servidor.

Crea un elemento por cada resultado
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}], esto crea dos elementos de lista: «Kindred (1979)» y «Beloved (1987)». Vaciar primero el contenedor hace que una nueva búsqueda sustituya a la anterior. Sin ese paso, las listas antigua y nueva se acumulan.

Mantén el texto externo como texto

Usa textContent para títulos, descripciones y otros textos de la API. innerHTML analiza una cadena como marcado. Un título que contenga <img src="x" onerror="alert(1)"> puede entonces ejecutar código. Esto son secuencias de comandos entre sitios, o XSS. El texto de formularios y almacenamiento necesita el mismo tratamiento porque también puede proceder de una fuente no confiable.

Las propiedades de los elementos establecen valores individuales, como img.alt = book.title. No hacen que todo tipo de valor sea seguro automáticamente. Un enlace proporcionado por una API sigue necesitando una comprobación del 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");
}

Este código se ejecuta sobre un enlace recién creado que no tiene un href. Una URL no válida o no permitida lo deja sin destino. Una URL javascript: no es navegación web normal. Para las imágenes, proporciona un texto alt significativo construido a partir de los datos cuando sea posible.

Proporciona valores predeterminados sin perder valores reales

Los campos opcionales pueden estar ausentes o ser null. book.author?.name ?? "Unknown author" primero intenta obtener el nombre anidado y después proporciona un valor predeterminado. El encadenamiento opcional evita acceder a una propiedad de un autor ausente.

El operador importa: 0 || "n/a" da "n/a", mientras que 0 ?? "n/a" conserva 0. El operador || sustituye todos los valores falsos en contexto booleano, incluidos el cero y una cadena vacía; ?? solo sustituye null y undefined. Un libro con cero ejemplares disponibles debe mostrar cero.

Un array de resultados vacío es una búsqueda correcta sin coincidencias. Muestra «Ningún libro coincide con tu búsqueda» para que los lectores puedan distinguirlo de una página que no se ha cargado.

Sustituye una búsqueda, añade otra página

Muchas API devuelven páginas usando page, limit, un recuento total o una URL next. Con 47 resultados y 10 por página, cuatro páginas completas contienen 40 registros y la quinta contiene 7. Una nueva búsqueda borra la lista anterior; «Cargar más» añade la siguiente página a la lista actual. Mantén separadas esas dos acciones de presentación.

Para ordenar una copia local con los más recientes primero, usa [...books].sort((a, b) => b.year - a.year) y renderiza esa copia. La propagación crea un array nuevo, por lo que el orden de la respuesta guardada sigue disponible. Inspecciona la estructura de la respuesta antes de seleccionar el array: una API paginada suele colocarlo dentro de data.results.

Puntos clave

  • Renderiza a partir de datos guardados para que la ordenación local no necesite una nueva solicitud.
  • Inserta texto no confiable con textContent.
  • Valida el protocolo de un enlace de API antes de asignar su destino.
  • Usa ?. para datos anidados ausentes y ?? cuando el cero deba seguir siendo cero.
  • Sustituye los resultados para una nueva búsqueda; añade resultados para otra página.

2.2 Da formato a fechas e importes para las personas

Las API devuelven valores que los programas pueden intercambiar fácilmente. Los lectores necesitan fechas, horas e importes con formato para su idioma y región. Mantén el valor almacenado separado del texto usado para mostrarlo.

Lee primero el formato de fecha

"2026-03-05T14:30:00Z" designa un instante: las 14:30 UTC del 5 de marzo de 2026. La Z significa UTC. new Date(...) lo convierte en un Date de JavaScript. Una cadena con solo la fecha, como "2026-03-05", se interpreta como medianoche UTC; una fecha y hora sin desplazamiento, como "2026-03-05T14:30", se interpreta como hora local.

Una marca de tiempo Unix cuenta desde el 1 de enero de 1970, UTC. Las API suelen contar segundos, pero Date recibe milisegundos. new Date(1772721000 * 1000) da el mismo instante del 5 de marzo. Omitir la multiplicación da una fecha de enero de 1970. Lee la documentación de la API para identificar la unidad.

Elige una configuración regional y una zona horaria
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);

La salida es «Mar 5, 2026, 2:30 PM». Con en-GB, es «5 Mar 2026, 14:30». El uso de fechas cortas produce «3/5/26» en en-US, «05/03/2026» en en-GB y «05.03.26» en de-DE.

La configuración regional controla la presentación; la zona horaria controla la hora local. Sin timeZone, el formateador usa la zona del dispositivo. Ese instante corresponde a las 9:30 de la mañana en Nueva York, las 15:30 en Ámsterdam y las 11:30 de la noche en Tokio. Conserva y envía los instantes en UTC y conviértelos para mostrarlos. Una fecha de calendario como un cumpleaños requiere cuidado: dar formato a la medianoche UTC en una zona al oeste de UTC puede mostrar el día anterior.

Mantén la moneda separada de la configuración regional
const priceFormat = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "EUR",
});
priceFormat.format(1234.5);

Esto da €1,234.50. Para el mismo importe, de-DE con EUR da 1.234,50 €; en-US con USD da $1,234.50; en-US con JPY da ¥1,235. JPY no tiene unidad monetaria fraccionaria, por lo que su presentación habitual no tiene decimales. Seleccionar una configuración regional no convierte entre monedas. Usa el código de moneda proporcionado con el importe.

Algunas API de pagos envían unidades fraccionarias enteras. Con USD, 1999 centavos significan 19.99 dólares: divide entre 100 antes de darles formato. No apliques ese divisor a JPY. Sumar centavos enteros da 1999 + 2550 = 4549, que se muestra como $45.49. Esto evita el conocido resultado de la aritmética decimal 0.1 + 0.2, que es 0.30000000000000004.

Reutiliza el formateador

Crea un formateador una vez para una lista. Usa undefined como configuración regional para seleccionar la opción predeterminada del navegador; navigator.language indica la etiqueta de idioma preferida del navegador. Otras opciones dan formato a 0.256 como «26%», o a 12.5 con la unidad "kilometer-per-hour" como «12.5 km/h». new Intl.RelativeTimeFormat("en", { numeric: "auto" }).format(-1, "day") da «yesterday». Las fechas construidas a mano, como «03/05/2026», siguen siendo ambiguas entre regiones.

Puntos clave

  • Comprueba si las marcas de tiempo usan segundos o milisegundos.
  • Una zona horaria explícita hace previsible la presentación de fecha y hora.
  • La configuración regional controla el formato; la moneda procede de los datos.
  • Convierte las unidades fraccionarias documentadas antes de dar formato a los importes monetarios.
  • Reutiliza los objetos formateadores de Intl en una lista.
  • Las cadenas con solo fecha se interpretan como UTC y pueden cambiar de día al mostrarse en otra zona.

2.3 Muestra qué está haciendo la solicitud

Una solicitud tiene un ciclo de vida visible: inactiva, en carga y después con éxito o con error. El éxito puede contener datos o un resultado vacío. La página debe explicar cada estado para que los lectores sepan si deben esperar, cambiar una búsqueda o volver a intentarlo.

Mantén juntos la preparación y el restablecimiento

En este manejador, getJSON comprueba el estado HTTP y analiza el cuerpo, searchUrl construye la URL de la solicitud y renderResults actualiza la lista. El botón y el elemento de estado ya existen en la 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;
  }
}

La preparación ocurre antes de la espera. La ruta de éxito renderiza los resultados y maneja un array vacío. El bloque catch sustituye el mensaje de carga si falla algún paso esperado. finally restablece el botón después de cualquiera de las dos rutas. Si el restablecimiento apareciera solo después de un await correcto, un fallo dejaría el control desactivado.

Explica la causa de forma útil

Un error HTTP tiene un estado que orienta el mensaje. Para 404, indica que no se encontró el elemento. Para 401, pide al usuario que inicie sesión; para 403, explica que no se permite el acceso. Para 429, pídele que espere. Para 5xx, explica que el servicio tiene un problema y sugiere intentarlo más tarde.

Un TypeError de fetch puede significar un fallo de red, una solicitud CORS bloqueada o una URL incorrecta. JavaScript no recibe un diagnóstico detallado fiable de CORS; inspecciona la consola del navegador y la pestaña Network. Un SyntaxError de json() apunta a un JSON no válido. Las cancelaciones y los tiempos límite producen errores como AbortError y TimeoutError. Conserva los detalles técnicos en la consola y ofrece a los lectores una acción que puedan entender.

Haz visibles los cambios

Usa un elemento de estado existente como <p role="status"></p>. Sus cambios se anuncian a los lectores de pantalla sin mover el foco. aria-live="polite" cumple una finalidad similar; role="alert" es adecuado para errores urgentes. Un indicador giratorio por sí solo no comunica un resultado vacío ni una solicitud fallida.

Un botón Reintentar vuelve a llamar a la función de carga. Reintentar solicitudes 400 o 404 sin cambios suele repetir el problema. Los fallos temporales de red o de servicio pueden justificar una secuencia breve y limitada de reintentos. La espera exponencial entre reintentos aumenta la pausa, por ejemplo 1 segundo, 2 segundos y después 4 segundos. Respeta la cabecera de respuesta Retry-After; puede indicar un retraso en segundos o una fecha HTTP. Evita reintentar automáticamente una solicitud de creación que podría haber tenido éxito.

Si falla una actualización pero los datos anteriores siguen siendo útiles, mantenlos visibles con una nota como «Se muestran los resultados de las 10:42. No se pudieron actualizar». No hagas que los resultados antiguos parezcan actuales sin avisar.

Prueba las situaciones difíciles

Usa las herramientas de desarrollo para ralentizar la conexión, desconectarte y solicitar una ruta que no existe. Comprueba que la carga aparezca rápidamente, que una solicitud fallida la sustituya, que un resultado correcto vacío tenga su propio mensaje y que los controles vuelvan a poder usarse.

Puntos clave

  • Haz visibles la carga, el éxito sin datos, el éxito con datos y los errores.
  • Coloca el restablecimiento compartido en finally.
  • Ofrece a los lectores una acción útil y conserva los detalles técnicos en la consola.
  • Anuncia las actualizaciones de estado mediante una región activa adecuada.
  • Limita los reintentos y respeta la espera solicitada por el servidor.

2.4 Controla las solicitudes simultáneas y en paralelo

Las solicitudes pueden continuar después de la acción que las inició. Una respuesta de búsqueda puede llegar después de que el lector haya escrito otra cosa, y un servicio lento puede dejar una página esperando demasiado tiempo. Controla qué resultados siguen siendo pertinentes, además de si cada solicitud tuvo éxito.

Cancela el trabajo que ya no necesitas

Crea un AbortController, pasa su signal a fetch y llama a abort() para cancelar la solicitud. La cancelación puede interrumpir tanto la espera de las cabeceras como una lectura del cuerpo en curso. El rechazo normalmente se llama "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();

Rodea ambas esperas de un manejo de errores. Si tu código cancela una búsqueda obsoleta a propósito, retorna sin avisar para esa cancelación esperada, en lugar de decir al usuario que el servicio falló.

fetch no tiene una opción timeout integrada. Usa una señal como AbortSignal.timeout(5000) para limitar la solicitud a 5000 ms, o 5 segundos de tiempo activo. Antes de que lleguen las cabeceras, se rechaza con TimeoutError; después de que lleguen, puede interrumpir la lectura del cuerpo.

Evita que prevalezcan las búsquedas antiguas

Una condición de carrera ocurre cuando el orden en que terminan las operaciones cambia el resultado. Un lector escribe «ca» y después «cat». Si «ca» llega la última y se renderiza, la pantalla deja de coincidir con la entrada.

Una opción cancela la solicitud anterior antes de cada nueva solicitud. Otra asigna un número a cada llamada y solo permite que la más reciente actualice la 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);
  }
}

La comprobación también impide que un fallo antiguo sustituya un éxito más reciente. Aplica la misma comprobación de pertinencia a los mensajes de carga y al restablecimiento de los controles cuando las llamadas se solapen.

La agrupación de llamadas tras un periodo de inactividad reduce el número de llamadas que se inician. Cancela el temporizador anterior en cada pulsación e inicia uno nuevo, por ejemplo de 300 ms. Al escribir «paris» rápidamente se inicia una solicitud después de la pausa. Esta agrupación ahorra solicitudes; por sí sola no impide que una respuesta anterior aún en curso llegue tarde.

Decide qué puede ejecutarse al mismo tiempo

Las solicitudes independientes pueden iniciarse juntas:

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

Para duraciones de 300 ms y 500 ms, las dos tardan unos 500 ms en lugar de unos 800 ms en secuencia. Promise.all se rechaza en cuanto se rechaza una de las promesas de entrada, pero no cancela las demás operaciones.

Usa Promise.allSettled cuando los resultados parciales sean útiles. Espera a todas las promesas de entrada e informa de cada una como { status: "fulfilled", value } o { status: "rejected", reason }. Un panel de control puede mostrar entonces las secciones que tuvieron éxito junto a una que falló.

Las solicitudes dependientes deben permanecer en secuencia. Si una segunda URL necesita un ID devuelto por la primera solicitud, espera ese ID antes de construir la segunda solicitud.

Puntos clave

  • Pasa una señal de cancelación antes de llamar a abort().
  • Captura los errores tanto de la obtención como de la lectura del cuerpo.
  • Ignora los resultados y los errores obsoletos.
  • La agrupación tras una pausa reduce las llamadas; una comprobación de pertinencia evita actualizaciones obsoletas.
  • Usa Promise.all para trabajos independientes que deben tener éxito juntos.
  • Usa Promise.allSettled cuando los resultados parciales sean útiles.
  • Espera los datos necesarios antes de iniciar una solicitud dependiente.
3

Lee datos de otros orígenes y protege las credenciales

Una solicitud puede parecer correcta y aun así fallar en un navegador porque la página y la API pertenecen a orígenes distintos. Ese límite está controlado conjuntamente por las reglas del navegador y las cabeceras de respuesta del servidor. Identificarás el origen, interpretarás los fallos de verificación previa y de CORS, y distinguirás el permiso para leer una respuesta del permiso para realizar una acción. Las credenciales requieren una decisión aparte: el usuario puede inspeccionar todo lo que se envía a un navegador.

3.1 Comprende el límite de origen del navegador

Un origen combina el esquema, el host y el puerto de una URL. Una ruta no forma parte de él. https://shop.example.com/cart y /help en el mismo sitio comparten un origen. Cambiar a http://shop.example.com, https://api.example.com o https://shop.example.com:8443 cambia el origen. HTTPS usa normalmente el puerto 443.

¿Quién permite leer la respuesta?

La política del mismo origen limita los recursos que puede leer un script de una página. Para una solicitud fetch a otro origen, CORS permite que el servidor de la API conceda acceso mediante cabeceras de respuesta. Una página en https://notes.example.org que llama a https://api.example.com/weather necesita el permiso de la API para leer la respuesta.

Access-Control-Allow-Origin: https://notes.example.org concede acceso a ese origen. El valor * permite cualquier origen para una solicitud sin credenciales. Si la respuesta no tiene un permiso que coincida, el navegador la oculta a la página y fetch se rechaza con un TypeError. La consola proporciona el diagnóstico de CORS; JavaScript no recibe el motivo detallado.

Añadir Access-Control-Allow-Origin a la solicitud de JavaScript no concede permiso. Es una cabecera de respuesta controlada por el servidor. Añadir una cabecera de solicitud personalizada puede generar una comprobación de verificación previa adicional.

Por qué aparece OPTIONS antes de POST

Algunas solicitudes a otros orígenes necesitan una verificación previa. El navegador envía primero OPTIONS, indicando el método previsto en Access-Control-Request-Method y los nombres de las cabeceras que no están en la lista permitida en Access-Control-Request-Headers. El servidor los permite con Access-Control-Allow-Methods y Access-Control-Allow-Headers, junto con el permiso del origen.

Una solicitud básica GET, HEAD o POST con solo cabeceras permitidas puede evitar la verificación previa. Los tipos de contenido permitidos incluyen text/plain, application/x-www-form-urlencoded y multipart/form-data. Un POST JSON, una cabecera Authorization, PUT o DELETE requiere verificación previa salvo que haya un permiso anterior válido en caché. Si se rechaza la verificación previa, la solicitud real no se envía.

Para una solicitud simple, la solicitud real puede llegar al servidor aunque después el navegador bloquee la lectura de su respuesta. Por eso CORS no sustituye la autorización del servidor ni la comprobación de los datos de entrada.

Las cookies añaden otro requisito

La opción predeterminada credentials: "same-origin" envía cookies solo para solicitudes del mismo origen. credentials: "include" también permite las cookies que cumplan las condiciones en solicitudes a otros orígenes. Las reglas SameSite y las políticas de cookies de terceros siguen aplicándose.

Para permitir que JavaScript lea una respuesta con credenciales, el servidor debe enviar Access-Control-Allow-Credentials: true e indicar explícitamente el origen de la página. Access-Control-Allow-Origin: * no funciona con credenciales. Estas cabeceras no obligan a un navegador a enviar una cookie que de otro modo estaría bloqueada.

Diagnostica sin ocultar el problema

mode: "no-cors" da una respuesta opaca con estado 0 y sin cuerpo ni cabeceras legibles. No puede proporcionar JSON a una página. Que una solicitud funcione en curl tampoco demuestra que exista permiso CORS en el navegador: los clientes de terminal no aplican esa política del navegador.

Inspecciona la consola y la pestaña Network. Comprueba si falló la verificación previa o si a la respuesta final le faltaba el permiso. Corrige la configuración de respuesta de la API o dirige la llamada a través de tu propio servidor. Durante el desarrollo, sirve las páginas desde un servidor local: las páginas file:// suelen tener orígenes opacos. Un servidor local sigue necesitando permiso CORS cuando llama a un origen distinto.

Puntos clave

  • Un origen consta de esquema, host y puerto.
  • Las cabeceras de respuesta del servidor conceden permiso de lectura entre orígenes.
  • La verificación previa comprueba el método y las cabeceras propuestos antes de la solicitud real.
  • CORS puede ocultar una respuesta después de que una solicitud simple ya se haya procesado.
  • Las respuestas con credenciales requieren un origen explícito y una cabecera de credenciales.
  • no-cors produce una respuesta opaca, no JSON legible.

3.2 Mantén las claves secretas fuera de la página

Una clave de API identifica a una aplicación que hace llamadas para controlar el uso, los límites y la facturación. Un token de acceso concede acceso a un usuario o una sesión. Cualquiera que posea una credencial utilizable puede actuar con su autoridad, así que decide dónde debe estar antes de añadirla a una solicitud.

Las cabeceras protegen la ubicación, no el secreto frente al usuario

Los proveedores pueden exigir Authorization: Bearer <token>, X-API-Key: <key> o un parámetro de consulta como api_key. Sigue la documentación de la API. Una cabecera evita incluir la credencial en una URL completa que puede acabar en registros y herramientas de análisis. Una cabecera Authorization o personalizada en una llamada a otro origen normalmente desencadena una verificación previa.

Una cabecera sigue siendo visible en las herramientas de desarrollo. Los visitantes pueden inspeccionar el JavaScript que descargan y las solicitudes que envía. Minificar el código u ocultar un valor detrás de una variable no lo convierte en secreto.

Sigue la clave en una solicitud meteorológica

Supongamos que el código del navegador llama a https://api.weather.example/v1/current?city=Lima&key=sk_live_4f9a2c. Cualquiera que abra Network puede copiar la clave y usar la cuota de la cuenta. Trasladar ese valor a una variable de entorno de compilación no ayuda si la compilación lo inserta en el JavaScript enviado a la página.

Un secreto guardado en el servidor cambia el recorrido:

  1. La página llama a su propio sitio en /api/weather?city=Lima.
  2. El servidor de ese sitio añade el secreto y contacta con el proveedor meteorológico.
  3. El servidor devuelve los datos meteorológicos a la página, manteniendo el secreto fuera de la respuesta.

El servidor sigue necesitando controlar el acceso y el uso de su punto de acceso. Mantener el secreto del proveedor en un servidor no hace que el uso público ilimitado sea inofensivo.

Algunos proveedores emiten claves para navegador destinadas a ser públicas. Aplica las restricciones de dominio del proveedor, limita las API permitidas y establece cuotas de uso. Usa una clave de este modo solo cuando su diseño documentado lo permita; una clave secreta de servidor no se convierte en clave para navegador por añadir una restricción de dominio.

Responde a una exposición

Mantén los archivos de credenciales fuera del control de versiones, por ejemplo incluyendo .env en .gitignore. Esto protege el archivo para que no se incluya en un commit; no impide que una compilación del cliente publique un valor que el código incorpora. Si una clave queda expuesta, revócala y genera una de reemplazo. Eliminarla del commit más reciente deja intactos el historial anterior y las copias.

Protege el intercambio y reduce el uso innecesario

Usa HTTPS para las llamadas a API, de modo que los datos y las credenciales se cifren durante el tránsito. Una llamada fetch de una página HTTPS a una API HTTP se bloquea por contenido mixto. El cifrado no impide que la persona que usa el navegador vea su propia solicitud.

Un límite de frecuencia restringe el uso, por ejemplo a 60 solicitudes por minuto. Las llamadas que superan el límite pueden devolver 429 Too Many Requests. Almacena en caché los resultados adecuados, agrupa las llamadas de búsqueda tras una pausa en la entrada y evita llamadas duplicadas. Si el servidor proporciona Retry-After, respeta su tiempo de espera en lugar de reintentar repetidamente de inmediato.

La validación del lado del cliente facilita el uso de los formularios, pero cualquiera puede llamar a un punto de acceso sin tu formulario. El servidor debe validar las solicitudes y autorizar las acciones por sí mismo. Al mostrar su respuesta, sigue tratando las cadenas como texto no confiable e insértalas con textContent.

Puntos clave

  • El código y las solicitudes enviados al navegador exponen las credenciales que contienen.
  • Una clave secreta debe estar en el servidor que llama al proveedor.
  • Restringe las claves públicas para navegador por dominio, API y cuota.
  • Revoca una clave expuesta; eliminarla del código actual no basta.
  • HTTPS cifra el tránsito, mientras que el servidor sigue validando y autorizando las solicitudes.
4

Conserva pequeñas cantidades de estado en el navegador

Una configuración o un borrador pueden sobrevivir a una recarga sin una nueva solicitud al servidor. El almacenamiento del navegador lo facilita, pero sus valores son cadenas y su duración depende del almacén que elijas. Guardarás y restaurarás pequeñas partes del estado, validarás los datos antiguos antes de usarlos y darás un tiempo de caducidad a los resultados de API almacenados en caché. También decidirás qué datos deben estar en otro lugar, ya que el almacenamiento local no es una caja fuerte para secretos ni la única copia segura de trabajos importantes.

4.1 Guarda cadenas y restaura sus tipos

Web Storage ofrece dos almacenes de pares clave-valor: localStorage y sessionStorage. Usan los mismos métodos, por lo que la elección principal es cuánto deben durar los datos y qué pestañas deben compartirlos.

Elige la duración
AlmacénDuraciónUso compartido
localStorageSobrevive al cierre de la pestaña y del navegador hasta que se elimina o borraCompartido por las páginas del mismo origen
sessionStorageSobrevive a las recargas durante la sesión de página de la pestañaSeparado para cada pestaña y origen

Cerrar la pestaña termina su almacenamiento de sesión. Una página recién abierta que tiene un control de apertura puede empezar con una copia del almacenamiento de sesión de la página que la abrió, pero los cambios posteriores permanecen separados. Evita usar el almacenamiento de sesión para mantener información en secreto frente a los scripts.

El almacenamiento sigue los orígenes. https://app.example.com no puede compartir su almacén con http://app.example.com. Las rutas del mismo origen sí lo comparten, por lo que un prefijo como "notes-app:settings" ayuda a distinguir las claves de varias aplicaciones.

Usa los métodos de almacenamiento
localStorage.setItem("notes-app:theme", "dark");
const theme = localStorage.getItem("notes-app:theme");
localStorage.removeItem("notes-app:theme");

setItem crea o sobrescribe una entrada. getItem devuelve su valor como cadena o null si está ausente. removeItem elimina una entrada. clear() elimina todas las entradas de esa área de almacenamiento para el origen, lo que puede afectar a otras funciones del mismo sitio. length y key(index) permiten inspeccionar las claves.

Usa estos métodos en lugar de asignaciones de propiedades como localStorage.theme = "dark". Las claves como "length" o "key" pueden entrar en conflicto con miembros integrados cuando se accede a ellas como propiedades.

Convierte los valores de forma explícita

Después de localStorage.setItem("count", 5), la lectura da "5". Sumar 1 directamente crea "51". Number(localStorage.getItem("count")) + 1 produce 6.

Un booleano almacenado presenta una trampa similar. setItem("darkMode", false) almacena "false", y una cadena no vacía es verdadera en contexto booleano. Lee con localStorage.getItem("darkMode") === "true" cuando esas sean las dos cadenas almacenadas esperadas.

Los objetos y arrays necesitan JSON:

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

Sin serialización, un objeto normal se convierte en "[object Object]". JSON.parse(null) da null, por lo que el valor predeterminado cubre una entrada ausente. Una cadena almacenada mal formada sigue necesitando try/catch, y los datos analizados necesitan una comprobación de estructura antes de usarse.

Mantén pequeña la carga de trabajo

Las llamadas a Web Storage son síncronas: JavaScript espera cada una en el hilo principal. Úsalo para configuraciones, un borrador o una lista breve, no para grandes colecciones o archivos. IndexedDB proporciona almacenamiento asíncrono para datos estructurados más grandes.

Los navegadores actuales suelen permitir unos 5 MiB en cada área de Web Storage por origen. Un almacén lleno puede hacer que setItem lance QuotaExceededError; el acceso también puede fallar por la configuración de privacidad del navegador. Maneja el fallo sin impedir que el resto de la aplicación funcione. Las herramientas de desarrollo muestran los almacenes en la pestaña Application de Chrome y Edge o en la pestaña Storage de Firefox, donde eliminar entradas ayuda a probar las primeras visitas.

Puntos clave

  • Elige localStorage para configuraciones compartidas persistentes y sessionStorage para el estado de la sesión de una pestaña.
  • Las áreas de almacenamiento están separadas por origen.
  • getItem devuelve una cadena o null.
  • Serializa objetos con JSON y restaura sus tipos al leerlos.
  • Maneja los fallos de almacenamiento y mantén pequeñas las escrituras síncronas.

4.2 Restaura el estado y establece la caducidad de los datos en caché

Una aplicación suele cargar al iniciar y guardar al cambiar. Lee una lista guardada cuando se abre la página, renderízala y guarda la lista actualizada después de una edición. El almacenamiento del navegador es una copia práctica: puede faltar, estar dañada o desactualizada, o borrarse.

Valida antes de restaurar

Esta función de carga espera un array guardado de cadenas:

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 por sí solo no demuestra que el valor sea un array ni que sus elementos sean adecuados para la aplicación. Un JSON válido como 42 sigue teniendo la estructura incorrecta. Un valor con versión como { version: 2, todos: [...] } permite que el código más reciente reconozca formatos antiguos y los convierta o restaure un valor predeterminado.

Guarda la lista en memoria con localStorage.setItem("todos", JSON.stringify(todos)) después de cada cambio. Captura también los fallos de escritura; una página debería poder seguir funcionando aunque no pueda conservar el estado para la siguiente recarga. Un borrador de formulario que pertenece solo a una visita puede usar sessionStorage.

Añade una marca de tiempo a las respuestas en caché
localStorage.setItem("weather", JSON.stringify({
  savedAt: Date.now(),
  data,
}));

En una carga posterior, valida primero la estructura y la marca de tiempo del objeto en caché. Su antigüedad es Date.now() - savedAt. Úsalo solo mientras esa antigüedad sea menor que 10 * 60 * 1000, o 600 000 ms. Un valor guardado a las 10:00:00 tiene 450 000 ms de antigüedad a las 10:07:30 y se puede usar. A las 10:12:00, tiene 720 000 ms de antigüedad, así que obtén un valor actualizado. Con exactamente 600 000 ms, ha caducado según esta regla.

La caducidad es lógica de la aplicación: localStorage no elimina una entrada cuando termina tu intervalo de vigencia. Rechaza una marca de tiempo ausente o no válida en lugar de tratar una antigüedad desconocida como reciente. Puedes mantener visibles los datos obsoletos durante una actualización fallida si los identificas como antiguos.

Sincroniza otras pestañas

Cuando una pestaña modifica localStorage, las demás pestañas del mismo origen reciben un evento storage. La pestaña que escribe no recibe su propio evento. El evento expone key, oldValue, newValue y url.

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

Aplica también el tema inmediatamente en la pestaña que escribe. Maneja null cuando se elimina una clave. Un evento de almacenamiento no sustituye la actualización del estado de tu propia página.

Decide qué debe estar en otro lugar

No guardes contraseñas, números de tarjetas de pago ni claves secretas de API en Web Storage. Los scripts del origen pueden leerlo, incluidos el código de terceros y los scripts inyectados. Borra los datos personales pertinentes al cerrar sesión en dispositivos compartidos. Guarda el trabajo importante en un servidor o permite exportarlo, porque los usuarios pueden borrar los datos del sitio y las sesiones privadas los descartan.

Las cookies son distintas: las solicitudes correspondientes las envían al servidor, y los scripts de la página no pueden leer las cookies HttpOnly. Son pequeñas, de unos 4 KB cada una. Web Storage permanece en el navegador y los scripts pueden leerlo. IndexedDB es adecuado para datos estructurados más grandes mediante una API asíncrona.

Puntos clave

  • Valida los datos analizados y recurre a una alternativa cuando falten o estén dañados.
  • La vigencia de la caché depende de una marca de tiempo y de un límite de antigüedad definido por la aplicación.
  • El evento storage llega a otras pestañas del mismo origen, no a la que escribe.
  • Mantén los secretos y los datos irremplazables fuera de Web Storage.
5

Usa las funciones de ubicación y portapapeles

Las API del navegador conectan una página con funciones como la ubicación y el portapapeles. Su disponibilidad depende del navegador, del contexto de seguridad de la página y de las decisiones del usuario. Detectarás una función antes de llamarla, pedirás permiso en un momento adecuado y manejarás tanto el éxito como la denegación. Una interacción completa incluye información visible y otra forma de terminar la tarea, como introducir una ciudad o copiar con el teclado el texto seleccionado.

5.1 Solicita una ubicación con una alternativa

La geolocalización es una API del navegador: una función proporcionada por el navegador, separada del lenguaje JavaScript. Como otras funciones del dispositivo, puede no estar disponible o ser denegada. Una página del tiempo debería seguir funcionando cuando un lector decide escribir una ciudad.

Comprueba la función y el contexto

Detecta la propia función con "geolocation" in navigator. Comprobar el nombre del navegador es menos fiable: las versiones y la configuración cambian lo que está disponible. La geolocalización necesita un contexto seguro, normalmente HTTPS; http://localhost también cumple el requisito para el desarrollo. window.isSecureContext indica si la página actual lo cumple. HTTP sin cifrar en la dirección de red de otro dispositivo no es lo mismo que localhost.

Explica por qué es útil la ubicación y solicítala cuando el lector haga clic en «Usar mi ubicación». El navegador gestiona la solicitud de permiso. Una persona puede permitirla o bloquearla, y una denegación anterior puede hacer que una llamada posterior falle sin otra solicitud. El usuario puede cambiar esa decisión en la configuración del sitio.

Lee el resultado de la función de devolución de llamada

navigator.geolocation.getCurrentPosition(success, error, options) usa funciones de devolución de llamada. Si tiene éxito, position.coords contiene la latitud y la longitud en grados decimales y accuracy en metros. La precisión es un radio estimado de incertidumbre, no una precisión decimal adicional. Si falla, el código 1 significa permiso denegado, 2 significa posición no disponible y 3 significa tiempo límite agotado.

Las opciones controlan el intento:

  • enableHighAccuracy: solicita mayor precisión; valor predeterminado false.
  • timeout: límite de espera en milisegundos; valor predeterminado Infinity.
  • maximumAge: antigüedad máxima de una posición aceptable almacenada en caché; valor predeterminado 0.

Usa un tiempo límite finito para que la página pueda dejar de esperar. watchPosition observa las actualizaciones a lo largo del tiempo y devuelve un ID; pasa ese ID a clearWatch cuando deba detenerse el seguimiento.

Envuelve las funciones de devolución de llamada al 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();
  }
}

Aquí showCityInput muestra el control de entrada manual y loadWeather solicita y renderiza el tiempo. Conecta useLocation al botón de ubicación. El bloque catch cubre el fallo de ubicación y la solicitud meteorológica; en ambos casos, la entrada manual sigue disponible.

Solicita solo la precisión útil

Una posición de latitud 52.3676, longitud 4.9041 y precisión 35 tiene un radio estimado de unos 35 m. Redondear a 52.37 y 4.90 reduce la precisión enviada al servicio meteorológico. Un intervalo de latitud de 0,01° equivale aproximadamente a 1,1 km; la separación de longitud varía con la latitud. Esa precisión regional es adecuada para una previsión sin compartir las coordenadas más detalladas.

Donde esté disponible la API de permisos, navigator.permissions.query({ name: "geolocation" }) informa de "granted", "denied" o "prompt". Detecta y maneja también esa API. Su estado ayuda a adaptar la interfaz, pero no sustituye el manejo de errores de la llamada de ubicación.

Puntos clave

  • Detecta la geolocalización y usa un contexto seguro.
  • Solicita la ubicación después de una acción clara del usuario y explicando el propósito.
  • La latitud y la longitud usan grados; la precisión usa metros.
  • Establece un tiempo límite finito y ofrece entrada manual si hay un fallo.
  • Envía solo la precisión de ubicación que necesita la función.
  • El estado del permiso no garantiza una posición utilizable.

5.2 Copia texto y aprende otra API del navegador

La API del portapapeles permite que una página copie texto sin pedir al lector que lo seleccione primero. Como la geolocalización, necesita comprobaciones de disponibilidad, una acción adecuada del usuario, manejo de errores y una alternativa.

Copia durante el clic

navigator.clipboard.writeText(text) devuelve una promesa. Espérala antes de informar del éxito. Se requiere un contexto seguro y una operación denegada puede rechazarse con NotAllowedError. Llámalo directamente desde un manejador de clic: Firefox y Safari requieren una interacción reciente del usuario, mientras que los requisitos de Chromium también pueden depender del permiso de escritura en el portapapeles.

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 es una entrada de texto o un área de texto y copyButton es el botón de la página. Si falla la copia, seleccionar el texto ofrece una opción con el teclado: Ctrl+C en muchos sistemas o Cmd+C en macOS. La etiqueta vuelve a ser «Copy» después de 2000 ms. Nunca muestres «Copied!» antes de que se cumpla la promesa.

La lectura usa navigator.clipboard.readText() y tiene controles más estrictos porque un portapapeles puede contener material privado de otras aplicaciones. Un navegador puede requerir permiso o mostrar una solicitud de pegado. El permiso para escribir no implica permiso para leer.

Trata la conectividad como una pista

navigator.onLine y los eventos online y offline de la ventana ayudan a mostrar un aviso de conexión. No indican con certeza si tu API es accesible. Un dispositivo puede tener conexión de red mientras el servidor de la API está caído o es inaccesible.

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

Sigue manejando los errores alrededor de fetch incluso cuando navigator.onLine sea verdadero. Usa una región activa adecuada para el mensaje de estado.

Lee una búsqueda que se pueda compartir

La API URL lee la cadena de consulta de la propia página, además de construir URL de API. En https://books.example.org/search?q=dune, new URL(location.href).searchParams.get("q") devuelve "dune". Lee ese valor al cargar la página para restaurar una búsqueda desde un enlace compartido. Un parámetro ausente devuelve null, así que decide qué debe mostrar entonces la pantalla inicial.

Usa un método de aprendizaje

Para otra API del navegador, lee su sintaxis, sus reglas de contexto seguro y permisos, su tabla de compatibilidad y su estado Baseline en MDN. Después detecta la función, llámala desde una acción del usuario cuando sea necesario, maneja su promesa o sus funciones de devolución de llamada y ofrece una alternativa cuando falte o se deniegue.

La API de notificaciones muestra notificaciones del sistema después de obtener permiso; Web Share abre un menú para compartir del dispositivo donde es compatible; Canvas dibuja gráficos; las API multimedia controlan el audio y el vídeo. Una API de mapas de terceros puede añadir una biblioteca y una clave del proveedor. Sus credenciales siguen las mismas reglas de claves secretas que las de cualquier otro servicio. Probar un navegador en localhost no demuestra que otro dispositivo o navegador tenga la misma compatibilidad y el mismo contexto.

Puntos clave

  • Espera a writeText antes de informar de que la copia tuvo éxito.
  • Conserva una alternativa para copiar con el teclado cuando falle el acceso al portapapeles.
  • La lectura del portapapeles tiene reglas de permiso distintas y más estrictas.
  • El estado de conexión no demuestra que la API sea accesible.
  • Usa parámetros de URL para restaurar una búsqueda que se pueda compartir.
  • Comprueba la compatibilidad, detecta funciones y maneja las denegaciones para cada API del navegador.

Ejemplos de Fetch y API del navegador

5 Lecciones Interactivas

1

Construye y actualiza una lista de lectura

14 pasos
Sigue una solicitud desde su URL hasta su respuesta JSON; después envía un registro nuevo y maneja el resultado del servidor.
  1. 1
    IntroducciónSigue un intercambio

    Una página de lista de lectura necesita cargar libros y añadir una nota sobre uno de ellos. La página es el cliente; la API es el servidor. Cada intercambio tiene una solicitud que describe la acción y una respuesta que describe su resultado.

    Primero interpretaremos el intercambio, después conectaremos los dos pasos asíncronos de la carga de JSON y, por último, enviaremos un cambio. La respuesta del servidor determina qué puede mostrar la página de forma segura a continuación.

  2. 2
    EjemploInterpreta el recurso y los filtros

    La página envía GET https://api.example.com/books?author=Le%20Guin&limit=5.

    GET solicita una lectura. /books identifica el recurso. La consulta filtra por autor y limita el número de resultados. %20 representa el espacio en «Le Guin». La documentación de la API determina estos nombres de parámetros; la página no puede elegir un nombre distinto y esperar que el servicio lo entienda.

  3. 3
    Idea claveDistingue el estado de la conexión

    Una respuesta puede indicar 200 OK con un libro o 404 Not Found con un error. Ambas demuestran que un servidor respondió. Un fallo de conexión no proporciona ningún estado HTTP a la página.

    Inspecciona la pestaña Network para ver la URL completa, el método, el estado, las cabeceras y el cuerpo. Si la API devolvió el JSON esperado, el siguiente lugar que debes inspeccionar es el código que lo lee o muestra.

  4. 4
    DesafíoElige un método para un cambio

    Ya existe una nota. La página debe modificar solo su campo done y conservar su texto. ¿Qué método HTTP corresponde a esa operación y por qué sería incorrecto usar GET?

    ---reveal---

    Usa PATCH para la actualización parcial. GET es un método de lectura seguro y no debe usarse para solicitar un cambio de datos. PUT describiría una sustitución completa y podría restablecer los campos omitidos del cuerpo.

  5. 5
    ExplicaciónEspera la respuesta

    Empieza con const response = await fetch(url). Esto espera hasta que llegan las cabeceras de la respuesta y proporciona un Response, no los libros analizados.

    La respuesta aún puede ser un error HTTP. fetch se cumple para un 404 porque existe una respuesta. Comprueba response.ok antes de considerar que la operación tuvo éxito; es verdadero para los códigos de estado de 200 a 299.

  6. 6
    EjemploComprueba y lee el cuerpo

    Continúa dentro de la función asíncrona:

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

    La segunda espera lee y analiza el cuerpo. Ahora data es un valor de JavaScript. Un try/catch exterior puede manejar tanto el error de estado lanzado aquí como los fallos al obtener o analizar el cuerpo.

  7. 7
    EjemploEncuentra el array anidado

    Supongamos que el cuerpo es {"results":[{"title":"Dune"}],"total":1}.

    El primer paso, data.results, accede al array. [0] accede a su primer objeto. .title da "Dune". Una función de renderizado debe recibir data.results, no todo el objeto exterior. La vista previa de la respuesta en Network es útil cuando la estructura de la API difiere de lo que esperaba la página.

  8. 8
    DesafíoDiagnostica el valor ausente

    El código usa const data = response.json() y después intenta acceder a data.results[0]. El cuerpo sí es JSON válido con un array results. ¿Qué falta?

    ---reveal---

    Espera el cuerpo: const data = await response.json(). Sin esa espera, data es una promesa y no tiene una propiedad results. El primer await fetch(...) no esperó también el análisis de JSON.

  9. 9
    ConsejoConserva los signos en una búsqueda

    Construye los parámetros de consulta mediante la API URL:

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

    El valor se convierte en rock+%26+roll. El signo & permanece dentro de la frase de búsqueda en lugar de dividir la consulta. Reutiliza la respuesta analizada después de cargarla: llamar a un segundo lector de cuerpo sobre la misma respuesta falla porque el cuerpo ya se consumió.

  10. 10
    EjemploPrepara un envío JSON

    Para crear una nota, serializa los campos e indica su formato:

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

    El método solicita la creación, la cabecera declara JSON y el cuerpo contiene texto JSON en lugar de un objeto normal.

  11. 11
    ConexiónUsa el registro almacenado

    El servidor puede devolver 201 Created con {"id":31,"title":"Read","done":false}. Añade ese registro devuelto al estado de la página. Su ID permite que una acción posterior llame a /notes/31.

    Para un formulario con archivos, pasa FormData en lugar de JSON y deja que el navegador establezca su delimitador multiparte. Una solicitud GET no puede llevar un cuerpo mediante fetch; los campos de búsqueda van en la cadena de consulta.

  12. 12
    DesafíoManeja un éxito sin cuerpo

    Al eliminar una nota guardada se devuelve 204. El código comprueba response.ok, después llama a response.json() y muestra un error. ¿Falló necesariamente la eliminación y qué debería cambiar?

    ---reveal---

    No: 204 indica que la operación terminó correctamente sin cuerpo. Omite el análisis de JSON para ese estado y actualiza la página después de comprobarlo. El fallo de análisis se debió a intentar leer contenido vacío, no a una prueba de que fallara la eliminación.

  13. 13
    DesafíoRevisa un flujo de envío completo

    Se puede hacer clic dos veces en un botón de guardar mientras se ejecuta un POST. Una respuesta correcta proporciona un ID nuevo. Indica los dos comportamientos de la página que evitan un duplicado accidental y conservan ese ID.

    ---reveal---

    Desactiva el botón durante la solicitud y restablécelo en finally. Si tiene éxito, actualiza a partir del registro devuelto, incluido su ID. El botón evita clics repetidos; el resultado del servidor proporciona valores que no existían en los datos enviados.

  14. 14
    RepasoComprueba el intercambio en cada paso

    Cuando una solicitud no funcione como esperas, inspecciona la operación en orden: la URL y el método documentados, el estado real, el lector de cuerpo elegido y la estructura de los datos entregados a la página.

    Para una escritura, comprueba también el tipo de contenido y el cuerpo serializado. Un éxito sin contenido no necesita un lector JSON. Una respuesta de creación debe proporcionar el registro guardado que se usará para la siguiente edición o eliminación.

2

Construye una página de búsqueda que se mantenga actualizada

18 pasos
Renderiza una lista, da formato a un precio y una fecha y mantén correcto el estado de las solicitudes durante búsquedas lentas, fallidas o simultáneas.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónMantén la pantalla vinculada a la búsqueda
  2. 2
    EjemploSustituye la lista anterior
  3. 3
    Idea claveDistingue el cero de los datos ausentes
  4. 4
    DesafíoManeja el texto y los enlaces externos
  5. 5
    EjemploIdentifica la unidad de tiempo
  6. 6
    ExplicaciónElige la zona de presentación
  7. 7
    EjemploDa formato a las unidades fraccionarias documentadas
  8. 8
    DesafíoSepara la configuración regional del valor
  9. 9
    ExplicaciónEmpieza con una espera visible
  10. 10
    EjemploTermina todas las rutas
  11. 11
    DesafíoReconoce una búsqueda correcta sin resultados
  12. 12
    ConsejoEspera antes de un reintento temporal
  13. 13
    EjemploObserva el orden de finalización
  14. 14
    EjemploCancela una solicitud obsoleta
  15. 15
    ConexiónReduce las llamadas mientras se escribe
  16. 16
    DesafíoElige el éxito parcial
  17. 17
    DesafíoProtege toda la interacción actual
  18. 18
    RepasoPrueba la interfaz con respuestas imperfectas
3

Diagnostica una llamada a una API de otro origen

10 pasos
Examina por separado el permiso de lectura del navegador, la autorización del servidor y la protección de una clave de proveedor.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónSepara dos cuestiones de permisos
  2. 2
    EjemploCompara los orígenes completos
  3. 3
    ExplicaciónInterpreta el permiso del servidor
  4. 4
    EjemploSigue primero la verificación previa
  5. 5
    DesafíoExplica un éxito solo en la terminal
  6. 6
    EjemploEncuentra la clave expuesta
  7. 7
    ConexiónTraslada el límite del secreto
  8. 8
    DesafíoDistingue el transporte del secreto
  9. 9
    DesafíoComprueba las cookies y las respuestas legibles
  10. 10
    RepasoDiagnostica el límite que falló
4

Restaura una lista guardada sin romper la página

12 pasos
Elige la duración del almacenamiento, conserva los tipos de datos, valida los datos restaurados y aplica una regla de vigencia de caché.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónConserva una copia local práctica
  2. 2
    ExplicaciónElige qué debe conservarse
  3. 3
    EjemploConserva un array como texto
  4. 4
    DesafíoRestaura el tipo previsto
  5. 5
    ConsejoManeja una escritura que supera la capacidad
  6. 6
    EjemploComprueba más que la sintaxis JSON
  7. 7
    EjemploAñade una hora a la caché
  8. 8
    DesafíoCalcula qué caché está vigente
  9. 9
    ConexiónSigue un tema entre pestañas
  10. 10
    Idea claveProtege los datos importantes
  11. 11
    DesafíoRecupérate de un formato guardado antiguo
  12. 12
    RepasoPrueba una primera visita y una visita posterior
5

Añade botones útiles de ubicación y copia

13 pasos
Construye interacciones que tengan en cuenta los permisos, con detección de funcionalidades, información clara y alternativas manuales.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónHaz que la acción sea comprensible
  2. 2
    ExplicaciónComprueba el contexto y la función
  3. 3
    ConsejoSolicita el permiso cuando la función sea útil
  4. 4
    EjemploEstablece una espera finita
  5. 5
    EjemploLee solo la precisión útil
  6. 6
    DesafíoRecupérate de una denegación
  7. 7
    EjemploEscribe durante el clic
  8. 8
    Idea claveEspera antes de confirmar la copia
  9. 9
    DesafíoTrata una señal de conexión como una pista
  10. 10
    ConexiónRestaura una búsqueda desde su enlace
  11. 11
    ConsejoComprueba otra función del navegador
  12. 12
    DesafíoRevisa ambos botones juntos
  13. 13
    RepasoPrueba también las decisiones de la persona

Ejercicios de Fetch y API del navegador

40 Preguntas de Práctica en 4 sets

Set 1: Solicitudes, resultados y funciones del navegador10 Preguntas de Práctica

Pregunta 1 de 10

Una respuesta tiene el estado 403. ¿Qué indica ese estado a la página?
  1. El servidor no pudo recibir la solicitud.
  2. El servidor necesita redirigir la URL del recurso.
  3. El servidor entendió la solicitud, pero la rechazó.
  4. El servidor aceptó la solicitud con un cuerpo vacío.
Mostrar respuestaOcultar respuesta
Respuesta: C
Una respuesta 403 significa que el servidor entendió la solicitud y se niega a cumplirla. No demuestra que el usuario haya proporcionado credenciales válidas ni que iniciar sesión vaya a resolver la denegación. Un fallo de conexión de red no proporcionaría un estado HTTP que la página pudiera leer.

Pregunta 2 de 10

Una API devuelve 200 con {"items":[{"name":"Cedar"}]}. ¿Qué asignación almacena el nombre del primer elemento después de 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 respuestaOcultar respuesta
Respuesta: A
Espera a que json() lea y analice el cuerpo y después sigue la propiedad exterior items hasta el primer objeto del array. Llamar a json() sin await deja una promesa que no tiene un array items. Leer con text() da una cadena, no el objeto analizado necesario para acceder a la propiedad.

Pregunta 3 de 10

Un punto de acceso acepta un cuerpo JSON. ¿Qué valor debe recibir body al enviar { label: "Read" }?
  1. JSON.parse({ label: "Read" })
  2. String({ label: "Read" })
  3. { label: "Read" }.toString()
  4. JSON.stringify({ label: "Read" })
Mostrar respuestaOcultar respuesta
Respuesta: D
JSON.stringify convierte el objeto en texto JSON válido para el cuerpo de la solicitud. Convertir un objeto normal con String o toString() produce "[object Object]", que el punto de acceso JSON no puede analizar. La solicitud también necesita el método documentado y una cabecera de tipo de contenido JSON.

Pregunta 4 de 10

Una API devuelve { remaining: 0, owner: null }. ¿Cómo puede la página mostrar el recuento restante y usar "Unknown" para el nombre de propietario ausente?
  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 respuestaOcultar respuesta
Respuesta: B
La coalescencia nula conserva el recuento válido de cero y el encadenamiento opcional evita leer name de null. Usar || para el recuento sustituye el cero porque es falso en contexto booleano. Una alternativa después de data.owner.name no puede ayudar cuando el acceso a name ya ha lanzado un error.

Pregunta 5 de 10

Una API documenta amount: 3785, currency: "USD" como unidades fraccionarias enteras. ¿Qué número debe recibir el formateador de moneda?
  1. 3785
  2. 37.85
  3. 378.5
  4. 0.3785
Mostrar respuestaOcultar respuesta
Respuesta: B
USD tiene 100 unidades fraccionarias por unidad principal, por lo que el entero documentado representa 37,85 dólares. Pasar 3785 directamente mostraría un importe 100 veces mayor. Intl.NumberFormat da formato al número que recibe; no deduce que un importe de API esté en centavos.

Pregunta 6 de 10

Una búsqueda desactiva su botón y después espera una solicitud. El botón solo se vuelve a activar después de renderizar resultados correctos. Una solicitud fallida lo deja desactivado. ¿Dónde debe ir la sentencia compartida que vuelve a activarlo?
  1. En la rama de éxito, después de borrar el estado.
  2. En un temporizador iniciado antes de comprobar la respuesta.
  3. En un bloque catch que sustituya todo el restablecimiento tras el éxito.
  4. En un bloque finally que rodee el trabajo esperado.
Mostrar respuestaOcultar respuesta
Respuesta: D
finally se ejecuta después del trabajo protegido tanto si tiene éxito como si lanza un error, por lo que es el lugar adecuado para el restablecimiento necesario en ambas rutas. Ponerlo solo en catch omite el éxito; dejarlo después del renderizado omite el fallo. Un temporizador restablecería los controles sin saber si la solicitud terminó.

Pregunta 7 de 10

Una página está en https://studio.example.org/edit. ¿Cuál es el origen de esa página?
  1. https://studio.example.org
  2. https://studio.example.org/edit
  3. https://example.org
  4. http://studio.example.org
Mostrar respuestaOcultar respuesta
Respuesta: A
El origen consta de esquema, host y puerto; HTTPS usa su puerto predeterminado cuando no se muestra ninguno. La ruta /edit identifica un recurso dentro del origen y no forma parte del origen. Cambiar el esquema a HTTP crearía un origen distinto incluso con el mismo host.

Pregunta 8 de 10

Una compilación del cliente lee una clave secreta del proveedor desde un archivo de entorno ignorado y la envía en una cabecera de solicitud HTTPS. Un visitante copia la clave desde Network. ¿Qué cambio protege una clave de reemplazo frente a los visitantes del navegador?
  1. Eliminar el archivo ignorado y mantener la misma compilación descargada.
  2. Recompilar con un nombre de variable más corto y mantener la cabecera.
  3. Revocar la clave expuesta y hacer que un servidor añada su reemplazo.
  4. Poner una clave de reemplazo en el cuerpo y eliminar la cabecera.
Mostrar respuestaOcultar respuesta
Respuesta: C
Revoca la clave copiada y después conserva el reemplazo en un servidor que llame al proveedor. Un archivo de entorno ignorado protege el control de versiones, pero una compilación del cliente aún puede publicar sus valores. HTTPS protege el tránsito y mover la clave entre campos de la solicitud del navegador no la oculta a su usuario.

Pregunta 9 de 10

Después de localStorage.setItem("visits", 8), ¿cuál es el valor de localStorage.getItem("visits") + 1?
  1. "81"
  2. 9
  3. "9"
  4. 81
Mostrar respuestaOcultar respuesta
Respuesta: A
Web Storage devuelve la cadena "8", por lo que + 1 concatena cadenas y da "81". No restaura el tipo numérico que se pasó a setItem. Convierte la cadena almacenada con Number antes de sumar si el resultado previsto es el número 9.

Pregunta 10 de 10

Una solicitud de ubicación falla con el código de error de geolocalización 1. ¿Qué respuesta dirigida al usuario corresponde al fallo?
  1. Explicar que se agotó el tiempo de ubicación y repetir de inmediato.
  2. Explicar que no existe una posición y ocultar el formulario del tiempo.
  3. Explicar que se denegó la ubicación y ofrecer la entrada de una ciudad.
  4. Explicar que no había una posición disponible y ofrecer otro intento.
Mostrar respuestaOcultar respuesta
Respuesta: C
El código de error de geolocalización 1 significa que se denegó el permiso, por lo que debes ofrecer otra forma de introducir la ubicación. El tiempo límite agotado es el código 3 y no explica este fallo. Las solicitudes repetidas no pueden forzar el permiso; una denegación recordada puede requerir que el usuario cambie la configuración del sitio en el navegador.
Set 2: Sigue los datos por la interfaz10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

Una llamada fetch devuelve un Response con estado 502. El código tiene un manejador catch, pero nunca comprueba response.ok. ¿Por qué podría no aparecer nunca su mensaje de error HTTP?
  1. Un error HTTP se rechaza solo después de que retorne el manejador catch.
  2. Un error HTTP cumple fetch; el código debe inspeccionar su estado.
  3. Una respuesta 502 se oculta hasta que se lee su cuerpo JSON.
  4. Un manejador catch recibe estados del servidor solo con no-cors.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

Un punto de acceso de eliminación documentado devuelve 204 cuando tiene éxito. ¿Qué debe hacer la página antes de intentar analizar JSON?
  1. Reconocer 204 como fallo y repetir la misma eliminación.
  2. Reconocer 204 como éxito y analizar un objeto vacío.
  3. Reconocer 204 como redirección y solicitar la misma URL.
  4. Reconocer 204 como éxito y omitir la lectura del cuerpo.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

Una nueva búsqueda añade sus elementos a los resultados anteriores. Un botón independiente «Cargar más» debe seguir añadiendo páginas. ¿En qué debe diferir el comportamiento de renderizado?
  1. Vaciar para una nueva búsqueda; añadir para otra página.
  2. Añadir para una nueva búsqueda; vaciar para otra página.
  3. Vaciar en ambas acciones antes de añadir sus resultados.
  4. Añadir en ambas acciones y eliminar solo elementos vacíos.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

Dos lecturas independientes tardan unos 240 ms y 680 ms. Sin contar los tiempos adicionales, ¿cuánto debería tardar esperar ambas mediante Promise.all?
  1. Unos 920 ms.
  2. Unos 240 ms.
  3. Unos 680 ms.
  4. Unos 440 ms.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

Comienza una búsqueda de «lo» y después una de «lotus». La finalización de una llamada antigua puede ocultar el nuevo mensaje de carga y un fallo antiguo puede sustituir los resultados más recientes. La cancelación no está disponible en la función envolvente de la solicitud. ¿Qué política de actualización mantiene toda la pantalla vinculada a la búsqueda actual?
  1. Solo las llamadas correctas comparan su número antes de renderizar.
  2. Solo las llamadas fallidas comparan su número antes de mostrar errores.
  3. Solo la llamada más reciente puede actualizar resultados, errores o carga.
  4. Cada llamada vacía la lista cuando termina su propia solicitud.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

Desde otro origen, una página envía un POST JSON con Content-Type: application/json. No hay ningún permiso de verificación previa en caché. ¿Qué debe comprobar el navegador antes de enviar ese POST?
  1. Una respuesta GET que contenga el mismo JSON que el POST previsto.
  2. Una respuesta OPTIONS que permita el origen, el método y las cabeceras.
  3. Una solicitud OPTIONS que contenga la cabecera de respuesta que permite el origen.
  4. Una respuesta POST que declare que la página desactivó las reglas del mismo origen.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

Un formulario de varios pasos debe sobrevivir a las recargas en su pestaña, pero terminar con la sesión de esa pestaña. ¿Qué opción de almacenamiento corresponde?
  1. Usar localStorage y dejar la entrada hasta que el código la elimine.
  2. Mantener el progreso solo en una variable de JavaScript en memoria.
  3. Usar localStorage y borrar la entrada cada vez que se carga la página.
  4. Usar sessionStorage para conservar el progreso actual de la pestaña.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

Una caché caduca después de 6 minutos. Se guardó a las 09:12:00 y se leyó a las 09:19:30. ¿Cómo debe tratarla la aplicación?
  1. Tiene 450 000 ms de antigüedad y necesita datos actualizados.
  2. Tiene 75 000 ms de antigüedad y puede usarse como vigente.
  3. Tiene 450 000 ms de antigüedad y puede usarse como vigente.
  4. Tiene 7500 ms de antigüedad y necesita datos actualizados.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

Una aplicación del tiempo funciona en http://localhost, pero su función de ubicación no aparece cuando se abre en un teléfono mediante una dirección de red HTTP. La aplicación también deja de funcionar cuando los usuarios de escritorio deniegan la ubicación. ¿Qué diseño resuelve ambos fallos?
  1. Reintentar la ubicación al cargar y ocultar la entrada de ciudad tras una denegación.
  2. Servir mediante HTTPS, detectar la geolocalización y mantener la entrada de ciudad.
  3. Comprobar el nombre del navegador y solicitar la ubicación sin límite de espera.
  4. Mantener HTTP, establecer alta precisión y eliminar las comprobaciones de permisos.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

Un manejador de copia espera navigator.clipboard.writeText(text). ¿En qué momento debe mostrar «¡Copiado!»?
  1. Después de que se cumpla esa promesa.
  2. En cuanto writeText devuelva.
  3. Cuando se supere la detección.
  4. Justo cuando el usuario haga clic.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Set 3: Depura solicitudes, almacenamiento y permisos10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

Un servicio documenta PUT /profiles/29 como sustitución del perfil. ¿Qué implica la idempotencia cuando se envía dos veces la misma solicitud completa?
  1. Las dos respuestas deben tener exactamente el mismo estado y las mismas cabeceras.
  2. La segunda solicitud debe rechazarse antes de llegar al servicio.
  3. El servidor debe crear un perfil nuevo por cada solicitud idéntica.
  4. El perfil almacenado previsto es el mismo que tras una solicitud.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

Una solicitud de creación agota el tiempo límite después de que el servidor haya podido recibirla. La página reintenta inmediatamente, renderiza solo los campos enviados y después envía una edición a un ID indefinido. ¿Qué diseño debe sustituir esta secuencia?
  1. Evitar repeticiones, resolver las creaciones inciertas y conservar los ID devueltos.
  2. Reintentar tras el tiempo límite, conservar los campos enviados y derivar los ID del orden de la lista.
  3. Evitar clics, reintentar cada tiempo límite y conservar solo los campos enviados.
  4. Permitir repeticiones, descartar los ID devueltos y usar la URL de creación para editar.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

Una API de eventos documenta su marca de tiempo en segundos. Una página la pasa directamente a new Date y muestra enero de 1970. ¿Qué conversión debe preceder al formato de la fecha?
  1. Dividir la marca de tiempo entre 1000.
  2. Añadir el desplazamiento UTC del lector.
  3. Multiplicar la marca de tiempo por 1000.
  4. Sustituir la configuración regional del formateador.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

Un catálogo conserva los datos de ayer después de que una actualización devuelva 503 con Retry-After: 12. ¿Qué comportamiento comunica el estado y facilita la recuperación?
  1. Ocultar el fallo y mostrar los datos antiguos como recién actualizados.
  2. Indicar que los datos son antiguos y esperar al menos 12 segundos antes de un reintento limitado.
  3. Vaciar la lista y repetir de inmediato hasta recibir un estado de éxito.
  4. Tratar la respuesta como un éxito sin datos y desactivar futuras actualizaciones.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

Una vista de cuenta necesita un perfil y el nombre de su equipo. El perfil devuelve teamId. Los avisos son independientes y pueden fallar sin ocultar los datos de la cuenta. ¿Cómo debe organizarse el trabajo?
  1. Iniciar todas las solicitudes juntas y rechazar toda la vista ante cualquier fallo.
  2. Ejecutar la cadena de perfil a equipo junto a los avisos y manejar cada resultado por separado.
  3. Esperar avisos, perfil y equipo en secuencia con un manejador de errores compartido.
  4. Iniciar los avisos después del perfil y el equipo solo si los avisos también tienen éxito.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

Una clave secreta de un proveedor se incluyó en un commit de un repositorio. ¿Qué acción aborda el uso de la credencial expuesta?
  1. Eliminarla solo del commit más reciente.
  2. Cambiarle el nombre en el código JavaScript.
  3. Trasladarla a una cabecera pública de solicitud.
  4. Revocarla y emitir una de reemplazo.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

Un booleano guardado se restaura con if (localStorage.getItem("compact")). El texto almacenado es "false", pero el modo compacto se activa. ¿Por qué?
  1. Web Storage restaura los valores booleanos con sus tipos originales.
  2. Una clave ausente devuelve la cadena "true" de forma predeterminada.
  3. Una cadena no vacía es verdadera en contexto booleano, aunque su texto sea "false".
  4. La sentencia if cambia el texto almacenado por un valor verdadero.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

Dos pestañas del mismo origen comparten el modo compacto como las cadenas «true» o «false». La pestaña A guarda «false», pero espera su propio evento storage; la pestaña B maneja el evento con Boolean(event.newValue). Eliminar la clave debe desactivar el modo compacto. ¿Qué regla de actualización maneja los tres casos?
  1. Aplicar cambios en la pestaña que escribe y en las que escuchan; activar solo para la cadena «true».
  2. Depender de eventos en ambas pestañas; activar para toda cadena almacenada no vacía.
  3. Aplicar cambios solo en la pestaña que escribe; conservar el modo anterior en las demás.
  4. Recargar la pestaña que escribe; usar Boolean con los valores del evento y conservar el modo tras la eliminación.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

Un resultado de ubicación tiene latitud -12.0464, longitud -77.0428 y precisión 80. ¿Qué describe 80?
  1. Una estimación de posición a 80 metros sobre el nivel del mar.
  2. Una probabilidad del 80 % de que la ubicación sea exacta.
  3. Una garantía de que el dispositivo está dentro de 80 metros.
  4. Un radio estimado de incertidumbre horizontal de 80 metros.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

Una página en https://recipes.example.org/search?q=green+tea lee new URL(location.href).searchParams.get("q"). ¿Qué valor obtiene?
  1. "green+tea"
  2. "q=green+tea"
  3. "green tea"
  4. null
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Set 4: Diseña funciones de API fiables10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

Una API limita una aplicación a 80 llamadas por minuto. Las solicitudes que superan ese límite reciben 429. ¿Qué significa ese estado?
  1. El registro solicitado ya no existe.
  2. Se hicieron demasiadas solicitudes.
  3. Se requiere una sustitución completa.
  4. El punto de acceso se trasladó de forma definitiva.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

Una búsqueda debe enviar el valor exacto «A+B & C». ¿Qué código establece ese valor sin tratar sus signos como estructura de la 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 respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

Un registro de API tiene un título que contiene texto literal <b>, un enlace javascript: y remaining: 0. La página debe mostrar el título literal, permitir solo enlaces web normales y conservar el recuento. ¿Qué plan de renderizado cumple las tres necesidades?
  1. Usar textContent, comprobar URL HTTP(S) y establecer el valor predeterminado con ??.
  2. Usar innerHTML, comprobar URL HTTP(S) y establecer el valor predeterminado con ??.
  3. Usar textContent, asignar cada href y establecer el valor predeterminado con ??.
  4. Usar textContent, comprobar URL HTTP(S) y establecer el valor predeterminado con ||.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

Dos lectores ven el mismo instante UTC con Intl.DateTimeFormat usando una configuración regional fija en-US, pero sin la opción timeZone. Las horas mostradas son distintas. ¿Qué explica la diferencia?
  1. La configuración regional elige el desplazamiento UTC de cada lector.
  2. El Date cambia su instante almacenado en cada dispositivo.
  3. El sufijo Z se ignora sin timeZone.
  4. El formateador usa la zona horaria de cada dispositivo.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

Una búsqueda devuelve JSON válido con un array de resultados vacío. Su manejador muestra el mensaje de error genérico y mantiene el botón desactivado. ¿Qué transición de estado corresponde a este resultado?
  1. Mostrar éxito sin datos, mantener la carga y seguir solicitando páginas.
  2. Mostrar fallo del servicio, borrar la carga y reintentar sin límite.
  3. Mostrar éxito sin datos, borrar la carga y restablecer el control.
  4. Mostrar éxito con datos antiguos y dejar el control desactivado.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

Un panel de control carga una cuenta en 400 ms y después necesita el ID devuelto para cargar un equipo en 200 ms. Las alertas independientes tardan 700 ms y pueden fallar sin ocultar los datos de la cuenta. ¿Qué organización permite ese comportamiento y cuánto tarda aproximadamente cuando todas las lecturas tienen éxito?
  1. Iniciar las tres juntas y rechazar la vista ante cualquier fallo; unos 700 ms.
  2. Ejecutar cuenta y después equipo junto a alertas, con ramas separadas; unos 700 ms.
  3. Ejecutar cuenta, equipo y alertas en secuencia con un catch compartido; unos 1300 ms.
  4. Ejecutar cuenta junto a alertas e iniciar equipo cuando ambas tengan éxito; unos 900 ms.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

Un PATCH JSON a otro origen usa credentials: "include". La verificación previa lo permite. La respuesta final tiene un comodín para el origen permitido y admite credenciales, por lo que JavaScript no puede leerla. El servidor también supone que CORS hace innecesarias las comprobaciones del usuario. ¿Qué política de respuesta y acceso corrige este diseño?
  1. Mantener el comodín, retirar el permiso de credenciales y autorizar cada acción.
  2. Indicar el origen de la página, mantener el permiso de credenciales y confiar en CORS como autorización.
  3. Mantener el comodín y el permiso de credenciales, pero autorizar cada acción.
  4. Indicar el origen de la página, mantener el permiso de credenciales y autorizar cada acción.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

Un proveedor documenta una clave de mapas como adecuada para uso público en el navegador. ¿Qué configuración limita los sitios, las operaciones de API y el uso total permitidos para esa clave?
  1. Restringir dominios y API, y establecer cuotas de uso.
  2. Restringir dominios y API, pero dejar el uso ilimitado.
  3. Restringir API y cuotas, pero permitir todos los dominios.
  4. Restringir dominios y cuotas, pero permitir todas las API.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

Una función de carga de borradores analiza texto guardado y llama inmediatamente a .map. Algunos usuarios tienen el JSON válido {"version":1,"items":[]} dejado por código antiguo y otros tienen texto dañado. ¿Qué plan de restauración maneja ambos casos?
  1. Capturar solo los fallos de escritura y usar cada valor analizado como array.
  2. Sustituir JSON.parse por JSON.stringify antes de llamar a .map.
  3. Capturar fallos de lectura o análisis y validar o convertir la estructura guardada.
  4. Usar ?? [] después del análisis y suponer que los valores no nulos son arrays.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

Un portátil indica navigator.onLine === true, pero una llamada a una API se rechaza. ¿Qué debe deducir la página sobre la conectividad y qué debe manejar después?
  1. La API es accesible; interpretar el rechazo solo como JSON no válido.
  2. Se detecta una red, pero la API aún puede ser inaccesible; manejar el fallo de la solicitud.
  3. La API es inaccesible; cambiar el indicador de conexión del navegador a falso.
  4. La API es accesible; reintentar inmediatamente hasta recibir una respuesta.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

¿Te atascas con una pregunta tuya? Ayuda con Tareas

Términos Clave

68 Términos Clave, cada uno con su definición

A

Activación del usuario
La activación del usuario es una interacción reconocida por el navegador, como un clic reciente, que puede requerirse antes de permitir una función restringida.
Llamar a la escritura en el portapapeles directamente en un manejador de clic proporciona la activación del usuario cuando el navegador la requiere.
Agrupación de llamadas tras un periodo de inactividad
La agrupación de llamadas tras un periodo de inactividad retrasa una operación hasta que se detienen los eventos repetidos y reinicia la espera después de cada evento para que una secuencia produzca menos llamadas.
Agrupar las llamadas de un campo de búsqueda evita enviar una solicitud por cada pulsación al escribir rápidamente una palabra.
Almacenamiento de sesión (sessionStorage)
sessionStorage es un almacenamiento web limitado a un origen y a la sesión de página de una pestaña, que conserva los valores entre recargas durante esa sesión.
Un formulario usa sessionStorage para un progreso que debe sobrevivir a una recarga sin convertirse en estado persistente compartido.
Almacenamiento local (localStorage)
localStorage es el área persistente de Web Storage de un origen, compartida por sus pestañas y conservada después de cerrar el navegador hasta que se elimina o borra.
Un tema guardado en localStorage puede restaurarse en la siguiente visita y leerse desde otra pestaña del mismo origen.
Almacenamiento web (Web Storage)
El almacenamiento web proporciona almacenes síncronos de pares clave-valor en el navegador para valores pequeños como cadenas, separados por origen y por la duración elegida.
El almacenamiento web conserva un objeto de configuración serializado que la página restaura cuando vuelve a iniciarse.
Alternativa de respaldo
Una alternativa de respaldo es otra forma de completar una tarea cuando la función preferida no es compatible, se deniega o no puede terminar.
Seleccionar un campo de enlace para copiar con el teclado proporciona una alternativa de respaldo cuando falla el acceso automático al portapapeles.
API del portapapeles
La API del portapapeles permite que una página lea o escriba de forma asíncrona el contenido del portapapeles del sistema, sujeta a las reglas del navegador sobre contexto seguro y acceso.
Un botón de copia usa la API del portapapeles después de un clic y espera antes de mostrar su mensaje de éxito.
API web
Una API web expone operaciones a las que un programa llama mediante URL para leer o modificar datos de otro sistema.
Una API web del tiempo permite que una página solicite la previsión de una ciudad sin cargar una página nueva.
Atributo HttpOnly
HttpOnly es un atributo de cookie que impide que el JavaScript de la página lea esa cookie, aunque esta pueda seguir acompañando a las solicitudes correspondientes.
Una cookie marcada con HttpOnly se diferencia de los datos de localStorage, que los scripts del origen pueden leer.

C

Cabecera HTTP
Una cabecera HTTP es un valor con nombre asociado a una solicitud o respuesta que describe el intercambio, su contenido o sus requisitos de acceso.
Una cabecera Content-Type indica al programa receptor que el cuerpo adjunto contiene JSON.
Cabecera Retry-After
La cabecera Retry-After indica a un cliente cuándo volver a intentarlo, mediante una espera en segundos o una fecha HTTP en una respuesta adecuada.
Un valor 15 de Retry-After pide a la página que espere quince segundos antes de otra solicitud.
Caché
Una caché es una copia guardada de datos que se usa para evitar repetir trabajo o solicitudes, con una política definida por la aplicación para decidir cuándo está vigente.
Una caché meteorológica puede mostrar inmediatamente una previsión reciente, mientras que una entrada caducada desencadena una nueva solicitud.
Caducidad
La caducidad es la antigüedad o el momento a partir del cual una aplicación deja de tratar un valor guardado como vigente, aunque siga almacenado.
Una caducidad de diez minutos hace que una aplicación compare la hora actual con la hora guardada junto con su respuesta en caché.
Clave de API
Una clave de API es una credencial que identifica a una aplicación que hace llamadas para que un proveedor pueda controlar el acceso, contabilizar el uso y aplicar límites o facturación.
Una clave de API visible en el navegador puede copiarse, por lo que una clave secreta del proveedor debe permanecer en el servidor que hace la llamada.
Coalescencia nula
La coalescencia nula proporciona una alternativa con ?? solo cuando el valor de su izquierda es null o undefined, y conserva los ceros válidos.
La coalescencia nula conserva un recuento de cero de una API en lugar de sustituirlo por el texto «no disponible».
Codificación de URL
La codificación de URL representa los caracteres de forma segura dentro de los componentes de una URL para que los signos de los datos no se confundan con la estructura de la dirección.
La codificación de URL mantiene el signo & del nombre de una banda dentro del valor de consulta en lugar de iniciar un nuevo parámetro.
Código de estado
Un código de estado es un valor HTTP de tres dígitos que informa del resultado de una solicitud, como éxito, denegación o un problema del servidor.
Un código de estado 201 indica a la página que el servidor creó un recurso en respuesta a la solicitud.
Condición de carrera
Una condición de carrera es un resultado que depende del orden en que termina el trabajo asíncrono, como cuando una búsqueda antigua sustituye resultados más recientes.
Una comprobación del número de solicitud evita una condición de carrera cuando una búsqueda anterior más lenta termina después de la actual.
Configuración regional
Una configuración regional identifica las convenciones de idioma y formato regional usadas para mostrar valores como fechas, números e importes monetarios.
La configuración regional en-US escribe una fecha de forma distinta a en-GB aunque ambas den formato al mismo instante.
Contenido mixto
El contenido mixto ocurre cuando una página segura solicita un recurso no seguro; los navegadores bloquean las llamadas fetch HTTP hechas por páginas HTTPS.
Una URL HTTP de previsión causa un fallo de contenido mixto cuando la propia página del tiempo se carga mediante HTTPS.
Contexto seguro
Un contexto seguro es un contexto del navegador considerado confiable para API restringidas, normalmente proporcionado por HTTPS o por un origen local que cumple los requisitos.
Un contexto seguro en localhost permite el desarrollo, mientras que una dirección de red HTTP sin cifrar puede no cumplir los requisitos.
Controlador de cancelación (AbortController)
Un controlador de cancelación proporciona una señal para una operación cancelable y puede solicitar su cancelación mediante su método abort.
La búsqueda crea un AbortController y pasa su señal a fetch antes de que una acción posterior lo cancele.
Cuerpo de la respuesta
El cuerpo de la respuesta es el contenido enviado después de las cabeceras de la respuesta; puede contener JSON, texto, datos binarios o ningún contenido.
La página lee el cuerpo de la respuesta una vez y conserva el objeto resultante tanto para renderizar como para filtrar.
Cuerpo de la solicitud
El cuerpo de la solicitud transporta contenido enviado a un servidor, como un registro JSON serializado o campos de formulario en una solicitud de creación.
El cuerpo de la solicitud contiene el título y el texto de una nota, mientras que el método especifica que debe crearse.
Cuota de almacenamiento
Una cuota de almacenamiento es un límite de datos almacenados impuesto por el navegador; superar el espacio disponible de Web Storage puede hacer que una escritura lance un error.
Una aplicación que mantiene una lista en memoria captura un error de cuota de almacenamiento y sigue usando esa lista aunque no pueda guardarla.

D

Datos de formulario (FormData)
FormData es un objeto del navegador que recopila campos y archivos de un formulario para enviarlos, lo que permite que fetch construya un cuerpo de solicitud multiparte.
Pasar FormData como cuerpo permite que el navegador envíe la imagen seleccionada junto a los campos de texto del formulario.
Delimitador de contenido multiparte
Un delimitador de contenido multiparte es la cadena que separa campos y archivos en un cuerpo multiparte y se identifica en su cabecera de tipo de contenido.
El navegador proporciona el delimitador de contenido multiparte cuando la página envía FormData sin establecer Content-Type por sí misma.
Detección de funcionalidades
La detección de funcionalidades comprueba si una función está disponible antes de que el código la use, lo que permite que la página elija una opción compatible o una alternativa.
La detección de funcionalidades con "geolocation" in navigator determina si la página puede ofrecer la ubicación del dispositivo.

E

Encadenamiento opcional
El encadenamiento opcional detiene de forma segura un acceso a una propiedad cuando el valor anterior a ?. es null o undefined y devuelve undefined.
El encadenamiento opcional permite que book.author?.name maneje un libro cuyo objeto de autor falta en la respuesta.
Error de análisis sintáctico
Un error de análisis sintáctico ocurre cuando un texto no puede interpretarse en el formato esperado, como una página HTML pasada a un lector de JSON.
Un cuerpo 204 vacío causa un error de análisis de JSON aunque el servidor haya completado correctamente la operación.
Espera exponencial entre reintentos
La espera exponencial entre reintentos aumenta la espera entre intentos mediante un factor multiplicador, reduciendo la carga repetida durante un fallo temporal.
La espera exponencial entre reintentos puede esperar uno, dos y cuatro segundos entre una secuencia limitada de intentos.
Estado de carga
Un estado de carga indica al lector que hay una operación asíncrona en curso mientras la página espera su resultado.
El estado de carga muestra «Buscando…» antes de que comience la solicitud y se borra cuando termina.
Estado sin datos
Un estado sin datos es la interfaz que se muestra después de que una operación correcta no devuelva datos coincidentes, lo que distingue ese resultado de un fallo.
El estado sin datos indica «Ningún registro coincide con tu filtro» después de que la API devuelve un array vacío válido.
Evento de almacenamiento
Un evento de almacenamiento notifica un cambio de almacenamiento a otros contextos del mismo origen que cumplan las condiciones; quien escribe en localStorage no recibe su propio evento.
Un evento de almacenamiento actualiza el tema en otra pestaña, mientras que la pestaña que escribe aplica el tema directamente.

F

Formateador Intl.NumberFormat
Intl.NumberFormat es un formateador de JavaScript que crea cadenas legibles de números, monedas, porcentajes o unidades para una configuración regional elegida.
La página reutiliza Intl.NumberFormat para cada precio en lugar de volver a construir una cadena monetaria para cada elemento.

G

Geolocalización
La geolocalización es una API del navegador que obtiene una posición estimada del dispositivo con permiso del usuario e informa del éxito o del fallo.
La geolocalización puede proporcionar coordenadas para una previsión cercana, con la entrada escrita de una ciudad disponible después de una denegación.

I

Idempotencia
La idempotencia significa que repetir una operación idéntica tiene el mismo efecto previsto sobre el estado del servidor que realizarla una vez.
Eliminar una nota dos veces ilustra la idempotencia: la nota sigue ausente aunque el segundo estado sea distinto.
IndexedDB
IndexedDB es la base de datos asíncrona del navegador para datos estructurados y archivos más grandes que no se ajustan bien a las tareas pequeñas de Web Storage.
Una página con una gran colección estructurada puede usar IndexedDB en lugar de escribirla repetidamente como una sola cadena de almacenamiento.
Indicador de compatibilidad Baseline
Baseline es el resumen de MDN sobre la disponibilidad de una función en los principales navegadores, que se usa junto con información detallada de compatibilidad y requisitos.
Consultar Baseline ayuda a planificar las pruebas en navegadores antes de que la página dependa de una API del navegador recién aprendida.
Intercambio de recursos entre orígenes (CORS)
CORS es el mecanismo de cabeceras HTTP que permite a un servidor autorizar a scripts de navegador de otros orígenes a leer sus respuestas.
La API usa CORS para permitir que una página de un sitio identificado lea sus datos meteorológicos desde otro host.

J

JSON
JSON es un formato de texto para datos estructurados, incluidos objetos y arrays, que debe analizarse antes de que el código use sus valores anidados.
La página analiza JSON y lee el array dentro de su propiedad results antes de construir los elementos de lista.

L

Límite de frecuencia de solicitudes
Un límite de frecuencia de solicitudes restringe cuántas operaciones puede realizar un cliente o una credencial en un intervalo de tiempo, lo que ayuda a un servicio a controlar el uso.
Una solicitud por cada pulsación puede superar un límite de frecuencia de búsqueda, por lo que agrupar las llamadas tras una pausa reduce las llamadas innecesarias.

M

Marca de tiempo Unix
Una marca de tiempo Unix mide el tiempo transcurrido desde el 1 de enero de 1970, UTC; la unidad documentada puede ser segundos o milisegundos.
Una marca de tiempo Unix en segundos necesita multiplicarse por 1000 antes de convertirse en un valor Date de JavaScript.
Método Promise.all
Promise.all combina las promesas de entrada en un array de resultados cuando todas se cumplen y se rechaza en cuanto se rechaza una de ellas.
La página usa Promise.all para dos lecturas independientes cuyos resultados deben estar disponibles para la presentación.
Método Promise.allSettled
Promise.allSettled espera a todas las promesas de entrada y devuelve un objeto de resultado para cada una, que indica su éxito o fallo.
Promise.allSettled permite que un panel de control muestre dos secciones correctas mientras explica el fallo de una tercera.

O

Objeto Response
Un objeto Response representa las cabeceras y el estado devueltos por fetch y proporciona métodos para leer el cuerpo de la respuesta.
El objeto Response tiene el estado 200, pero la página aún espera json() para obtener los datos del libro.
Operación síncrona
Una operación síncrona termina antes de que continúe la siguiente sentencia, por lo que una llamada de almacenamiento larga puede bloquear el hilo principal de la página.
Una escritura grande en Web Storage es una operación síncrona que puede retrasar el manejo de la siguiente interacción del usuario.
Origen
Un origen es la combinación del esquema, el host y el puerto de una URL que el navegador usa para definir varios límites de acceso.
Dos rutas en un mismo host HTTPS comparten origen, pero cambiar ese host o su puerto crea otro origen.

P

Paginación
La paginación divide una colección de resultados en grupos más pequeños que una API devuelve por separado, normalmente mediante parámetros de página o cursor.
La paginación permite que un botón «Cargar más» solicite el siguiente grupo y conserve los elementos ya mostrados.
Parámetro de consulta
Un parámetro de consulta es un valor con nombre en la parte de una URL posterior a ?, que un punto de acceso usa para entradas como búsquedas o límites de página.
El parámetro de consulta limit=12 pide al punto de acceso de búsqueda que devuelva como máximo doce resultados.
Permiso
Un permiso es una decisión gestionada por el navegador que autoriza o deniega a una página el acceso a una función protegida, como la ubicación del dispositivo.
Una denegación de permiso recordada puede hacer que falle una solicitud de ubicación sin mostrar una segunda petición.
Política del mismo origen
La política del mismo origen es un límite de seguridad del navegador que restringe cómo puede leer un script los recursos que pertenecen a otro origen.
La política del mismo origen hace que una solicitud fetch a otro origen dependa del permiso de lectura CORS del servidor de la API.
Precisión de la ubicación
La precisión de la ubicación describe la incertidumbre horizontal estimada alrededor de una posición indicada, medida en metros en lugar de grados.
Una precisión de ubicación de 60 metros describe el radio estimado de incertidumbre alrededor de la posición indicada.
Propiedad textContent
La propiedad textContent lee o establece el texto de un elemento sin interpretar la cadena proporcionada como marcado HTML.
Asignar un título a textContent muestra sus corchetes angulares literalmente en lugar de crear un elemento HTML.
Punto de acceso de la API
Un punto de acceso de la API es una dirección de API que acepta una solicitud documentada para un recurso u operación, a menudo mediante un método HTTP concreto.
El punto de acceso de notas acepta un POST para crear una nota y devuelve el identificador del nuevo registro.

R

Región activa
Una región activa es un área de la página cuyos cambios de contenido pueden ser anunciados por la tecnología de asistencia sin mover el foco del teclado.
Una región activa con role="status" anuncia «Cargando…» y el mensaje posterior con los resultados de búsqueda.
Renderizado
El renderizado convierte datos en contenido visible de una página, por ejemplo al crear un elemento de lista para cada objeto de un array de resultados de una API.
El renderizado de una nueva búsqueda comienza vaciando la lista anterior y después añadiendo los elementos de los resultados actuales.
Respuesta HTTP
Una respuesta HTTP es la contestación de un servidor a una solicitud, que contiene un código de estado, cabeceras y normalmente un cuerpo con datos o un error.
La respuesta HTTP indica 404 y explica en su cuerpo que no se encontró el libro solicitado.
Respuesta opaca
Una respuesta opaca oculta los detalles de su estado, sus cabeceras y su cuerpo al código de la página y expone un valor de estado de cero.
Una solicitud fetch no-cors da una respuesta opaca, por lo que la página no puede extraer el JSON que esperaba mostrar.

S

Secuencias de comandos entre sitios (XSS)
Las secuencias de comandos entre sitios consisten en la ejecución de scripts no confiables en una página, lo que puede ocurrir cuando las cadenas externas se interpretan como HTML.
Usar textContent para los títulos de una API elimina la interpretación como HTML que puede permitir secuencias de comandos entre sitios.
Señal de cancelación (AbortSignal)
Una señal de cancelación conecta una cancelación o un tiempo límite a una operación asíncrona como fetch y a la lectura de su cuerpo en curso.
Una señal de cancelación de AbortSignal.timeout(4000) limita una solicitud a cuatro segundos de tiempo activo.
Serialización
La serialización convierte un valor en un formato que puede almacenarse o transmitirse, como al convertir un objeto JavaScript en texto JSON.
La serialización con JSON.stringify conserva los campos de una nota cuando se envían como cuerpo JSON de una solicitud.
Solicitud de verificación previa
Una solicitud de verificación previa es una solicitud OPTIONS enviada por el navegador que comprueba el permiso entre orígenes para un método y unas cabeceras de solicitud previstos.
Un POST JSON puede necesitar una verificación previa antes de que el navegador envíe el registro que la página quiere crear.
Solicitud HTTP
Una solicitud HTTP es un mensaje de un cliente a un servidor con un método, una URL, cabeceras y, para algunas operaciones, un cuerpo.
La solicitud HTTP pide /books e incluye un parámetro de consulta que limita el número de resultados.

T

Tiempo universal coordinado (UTC)
El tiempo universal coordinado (UTC) es la referencia temporal compartida para identificar instantes entre zonas horarias, representada por Z al final de una fecha y hora ISO.
La API devuelve un instante en UTC y la página da formato a ese instante para un lector en otra zona horaria.
Token de acceso
Un token de acceso es una credencial que concede un acceso definido a un usuario o una sesión y permite a quien lo posee hacer las solicitudes autorizadas.
La cabecera Authorization de la solicitud transporta un token de acceso para la operación permitida del usuario que inició sesión.

U

Unidad monetaria fraccionaria
Una unidad monetaria fraccionaria es una subdivisión de la unidad principal de una moneda, como un centavo de USD, que algunas API usan para importes enteros.
Cuando una API documenta unidades monetarias fraccionarias de USD, el entero 4680 representa 46.80 dólares.

Z

Zona horaria
Una zona horaria determina la fecha de calendario y la hora local usadas para mostrar un instante, incluidas las reglas de desplazamiento aplicables.
Una zona horaria UTC explícita hace que todos los lectores vean la hora de un evento en UTC en lugar de en la zona de su dispositivo.

Sobre esta unidad

Por StudeliInformar de un error

Crea tus propios Materiales de Estudio

Convierte tus notas, diapositivas y documentos en Guías de Estudio, Preguntas de Práctica, Flashcards y 6 herramientas más.

Comenzar