# Construir una App Bancaria Parte 3: Métodos para Obtener y Usar Datos ## Cuestionario Previo a la Clase [Cuestionario previo a la clase](https://ff-quizzes.netlify.app/web/quiz/45) ### Introducción En el núcleo de cada aplicación web está *la información*. La información puede tomar muchas formas, pero su propósito principal siempre es mostrar datos al usuario. Con las aplicaciones web volviéndose cada vez más interactivas y complejas, cómo el usuario accede e interactúa con la información es ahora una parte clave del desarrollo web. En esta lección, veremos cómo obtener datos de un servidor de manera asincrónica y usar estos datos para mostrar información en una página web sin recargar el HTML. ### Prerrequisitos Necesitas haber construido la parte de la aplicación web [Formulario de Inicio de Sesión y Registro](../2-forms/README.md) para esta lección. También necesitas instalar [Node.js](https://nodejs.org) y [ejecutar la API del servidor](../api/README.md) localmente para obtener datos de cuentas. Puedes probar que el servidor está funcionando correctamente ejecutando este comando en una terminal: ```sh curl http://localhost:5000/api # -> should return "Bank API v1.0.0" as a result ``` --- ## AJAX y obtención de datos Los sitios web tradicionales actualizan el contenido mostrado cuando el usuario selecciona un enlace o envía datos usando un formulario, recargando la página HTML completa. Cada vez que se necesitan cargar nuevos datos, el servidor web devuelve una página HTML completamente nueva que debe ser procesada por el navegador, interrumpiendo la acción actual del usuario y limitando las interacciones durante la recarga. Este flujo de trabajo también se conoce como una *Aplicación de Múltiples Páginas* o *MPA*.  Cuando las aplicaciones web comenzaron a volverse más complejas e interactivas, surgió una nueva técnica llamada [AJAX (JavaScript y XML Asíncronos)](https://es.wikipedia.org/wiki/AJAX). Esta técnica permite a las aplicaciones web enviar y recuperar datos de un servidor de manera asincrónica usando JavaScript, sin tener que recargar la página HTML, lo que resulta en actualizaciones más rápidas e interacciones más fluidas. Cuando se reciben nuevos datos del servidor, la página HTML actual también puede ser actualizada con JavaScript usando la API del [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model). Con el tiempo, este enfoque ha evolucionado hacia lo que ahora se llama una [*Aplicación de Página Única* o *SPA*](https://es.wikipedia.org/wiki/Aplicaci%C3%B3n_de_p%C3%A1gina_%C3%BAnica).  Cuando se introdujo AJAX por primera vez, la única API disponible para obtener datos de manera asincrónica era [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). Pero los navegadores modernos ahora también implementan la más conveniente y poderosa [`Fetch` API](https://developer.mozilla.org/docs/Web/API/Fetch_API), que utiliza promesas y es más adecuada para manipular datos JSON. > Aunque todos los navegadores modernos soportan la `Fetch API`, si deseas que tu aplicación web funcione en navegadores antiguos o heredados, siempre es una buena idea verificar primero la [tabla de compatibilidad en caniuse.com](https://caniuse.com/fetch). ### Tarea En [la lección anterior](../2-forms/README.md) implementamos el formulario de registro para crear una cuenta. Ahora agregaremos código para iniciar sesión usando una cuenta existente y obtener sus datos. Abre el archivo `app.js` y añade una nueva función `login`: ```js async function login() { const loginForm = document.getElementById('loginForm') const user = loginForm.user.value; } ``` Aquí comenzamos recuperando el elemento del formulario con `getElementById()`, y luego obtenemos el nombre de usuario del campo de entrada con `loginForm.user.value`. Cada control de formulario puede ser accedido por su nombre (establecido en el HTML usando el atributo `name`) como una propiedad del formulario. De manera similar a lo que hicimos para el registro, crearemos otra función para realizar una solicitud al servidor, pero esta vez para obtener los datos de la cuenta: ```js async function getAccount(user) { try { const response = await fetch('//localhost:5000/api/accounts/' + encodeURIComponent(user)); return await response.json(); } catch (error) { return { error: error.message || 'Unknown error' }; } } ``` Usamos la API `fetch` para solicitar los datos de manera asincrónica al servidor, pero esta vez no necesitamos ningún parámetro adicional aparte de la URL a llamar, ya que solo estamos consultando datos. Por defecto, `fetch` crea una solicitud HTTP [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET), que es lo que buscamos aquí. ✅ `encodeURIComponent()` es una función que escapa caracteres especiales para URLs. ¿Qué problemas podríamos tener si no llamamos a esta función y usamos directamente el valor de `user` en la URL? Ahora actualicemos nuestra función `login` para usar `getAccount`: ```js async function login() { const loginForm = document.getElementById('loginForm') const user = loginForm.user.value; const data = await getAccount(user); if (data.error) { return console.log('loginError', data.error); } account = data; navigate('/dashboard'); } ``` Primero, como `getAccount` es una función asincrónica, necesitamos usar la palabra clave `await` para esperar el resultado del servidor. Como con cualquier solicitud al servidor, también debemos manejar los casos de error. Por ahora, solo agregaremos un mensaje de registro para mostrar el error y volveremos a esto más adelante. Luego, debemos almacenar los datos en algún lugar para poder usarlos más tarde y mostrar la información del tablero. Dado que la variable `account` aún no existe, crearemos una variable global para ella en la parte superior de nuestro archivo: ```js let account = null; ``` Después de que los datos del usuario se guarden en una variable, podemos navegar desde la página de *login* al *dashboard* usando la función `navigate()` que ya tenemos. Finalmente, necesitamos llamar a nuestra función `login` cuando se envíe el formulario de inicio de sesión, modificando el HTML: ```html