Envío de solicitudes AJAX en Vue.js

Javascript asíncrono y XML (AJAX), es una forma de comunicarse con un servidor web desde una aplicación del lado del cliente a través del protocolo HTTP o HTTPS. Incluso tú...

¿Qué es AJAX?

Javascript asíncrono y XML (AJAX) es una forma de comunicarse con un servidor web desde una aplicación del lado del cliente a través del protocolo HTTP o HTTPS.

Aunque AJAX contiene XML en el nombre, la forma en que los datos se envían a través de solicitudes o se reciben no tiene que ser XML, sino también texto sin formato, o en la mayoría de los casos JSON, debido a que es más ligero y parte de JavaScript en y de sí mismo.

¿Por qué es útil AJAX? {#por qué es útil}

Vue.js se usa como un marco de front-end, y si alguna vez desea comunicarse con un servidor, recuperar o almacenar información en una base de datos o realizar algunos cálculos en sus datos lo más probable es que necesite AJAX.

Aunque AJAX se puede usar creando un objeto XMLHttpRequest, que estará disponible a través del navegador. Hay ciertos paquetes que pueden ayudarnos a comunicarnos con nuestro servidor.

Vue.js tiene un paquete oficial llamado vue-resource que funciona como un cliente HTTP, pero la documentación oficial sugiere usar [Axios] (https://github.com/axios).

Instalación de Axios y configuración de un componente

Axios es un cliente HTTP y se puede instalar en nuestras dependencias package.json a través del administrador de paquetes de su elección, ya sea NPM o Yarn:

1
2
3
$ npm install axios
OR
$ yarn add axios

Después de la instalación, podemos configurar un componente de prueba minimalista con fines de demostración:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Test.vue
<template>
  <div/>
</template>

<script>
export default {
  data() {
    return {};
  };
}
</script>

Uso de Axios en Vue Components

Las solicitudes a un servidor a través de HTTP tardan cierto tiempo en devolverse con una respuesta y, para asegurarse de que la información que se muestra al usuario sea correcta, se deberán usar promesas para asegurarse de que los datos hayan regresado antes. continuando con nuestra ejecución de código.

Para usarlo en un componente, simplemente importamos el paquete y lo asignamos a una variable:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// Test.vue
<script>
import axios from "axios";

export default {
  data() {
    return {};
  }
};
</script>

Por lo general, las llamadas a la API se realizan dentro del enlace del ciclo de vida montado de Vue.

Vamos a utilizar un servicio de datos JSON simulado llamado JSONMarcador de posición. Esta es una simulación de cómo se verá un punto final de back-end al acceder a una API REST:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// Test.vue
<script>
import axios from "axios";

export default {
  data() {
    return {};
  },
  mounted() {
    axios.get("https://jsonplaceholder.typicode.com/todos/")
  }
};
</script>

En el ejemplo de código anterior, el componente se procesa antes de que llegue la información de JSONPlaceholder. Por lo tanto, el uso de promesas asegurará que podamos manejar los datos y agregarlos a nuestra vista.

Manejo de respuestas con luego()

La función then() nos permite manipular nuestra promesa y decirle a nuestro código qué vamos a hacer si/cuando la solicitud fue exitosa. Podemos, por ejemplo, con una función de devolución de llamada, verificar nuestra respuesta en la consola:

1
2
3
4
mounted() {
  axios.get("https://jsonplaceholder.typicode.com/todos/")
    .then(response => console.log(response))
}

browser_console_picture

Se ha devuelto una respuesta y podemos verla dentro de la consola del navegador, pero, ¿cómo le mostramos al usuario la lista de todos?

Deberíamos mantener la lista de todos dentro del objeto datos para futuras referencias dentro del DOM.

Lo llamaremos todosList, y copiaremos la propiedad de datos del objeto de respuesta de forma inmutable (para que no cambiemos el objeto de respuesta real) usando el operador Javascript spread y solo mostramos el primero 10 elementos, usando la función array slice, para que no carguemos cientos de todos:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<script>
import axios from "axios";

export default {
  data() {
    return {
      todosList: []
    };
  },
  mounted() {
    axios.get("https://jsonplaceholder.typicode.com/todos/")
      .then(response => {
         this.todosList = [...response.data].slice(0, 10)
      })
  }
};
</script>

Manejo de errores con catch()

¿Qué sucede si la solicitud falla? El estado de la aplicación deberá gestionarse en consecuencia. Para eso tenemos la función catch(), que se puede anidar en nuestra pila de funciones:

1
2
3
4
5
6
7
8
mounted() {
  axios.get("https://jsonplaceholder.typicode.com/todos/")
    .then(response => console.log(response))
    .catch(err => {
       // Manage the state of the application if the request 
       // has failed      
     })
}

De esta forma, vemos que aparece el error y podemos hacer muchas cosas con él, como mostrar un mensaje de error al usuario como una alerta o mostrar una tarjeta que diga "No Todos Disponibles". Las posibilidades son infinitas.

Mostrando los Todos

Usando la directiva v-for Vue podemos inyectar nuestros todos dentro de la plantilla y agregar algunos estilos con fines visuales:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<template>
  <div>
    <ul 
      class="test-list" 
      v-for="todo in todosList" 
      :key="todo.id"
    >
      <li class="test-list--item">
        {{ todo.id }}
      </li>
    </ul>
  </div>
</template>

<script>
import axios from "axios";

export default {
  data() {
    return {
      todosList: []
    };
  },
  mounted() {
    axios.get("https://jsonplaceholder.typicode.com/todos/")
      .then(response => {
         this.todosList = [...response.data].slice(0, 10)
      })
      .catch(err => {
         // Manage the state of the application if the request 
         // has failed      
      })
  }
};
</script>

<style>
.test-list {
  font-family: Roboto;
  list-style: none;
  margin: 20px auto;
  width: 50%;
}

.test-list--item {
  border: 1px solid rgb(41, 41, 41);
  border-radius: 5px;
  text-align: center;
  display: block;
  box-shadow: 2px 2px rgba(138, 124, 124, 0.4);
}

.test-list--id {
  font-weight: 300;
  margin: 10px auto;
}

.test-list--title {
  font-weight: 500;
  margin: 20px auto;
  text-transform: capitalize;
}

.test-list--complete {
  font-weight: 600;
  margin: 10px auto;
  color: #56ca86;
}

.test-list--incomplete {
  font-weight: 600;
  margin: 10px auto;
  color: #ca5656;
}
</style>

Si revisamos nuestro navegador, veremos algo como esto:

http_request_sent

¡Felicitaciones, acabamos de enviar una solicitud HTTP a una API y mostramos los datos al usuario!

Async/Await frente a Promesas

Async/Await es una construcción de lenguaje relativamente nueva de JavaScript que hace que nuestro código asíncrono sea mucho más limpio.

Aunque las llamadas Async/Await se convertirán en promesas al final, transmite un enfoque diferente, ya que ya no necesitamos configurar funciones de devolución de llamada para nuestro código, ¡todos sabemos cuánto las odiamos!

Nuestro código de ejemplo, que usa Async/Await, se parecería a lo siguiente, al tiempo que agrega algo de magia de desestructuración de objetos para que nuestro código se vea aún mejor:

1
2
3
4
5
6
// Test.vue
async mounted() {
    const url = 'https://jsonplaceholder.typicode.com/todos/'
    const { data } = await axios.get(url)
    this.todosList = [...data].slice(0, 10)
}

El enlace del ciclo de vida montado tiene como prefijo la palabra clave async. Esto asegura que el gancho devuelva una promesa.

Dentro del gancho, la palabra clave await hace que la función llamada espere a que continúe su resolución.

Conclusión

AJAX es una parte clave del desarrollo web moderno y, aunque puede parecer desalentador al principio, es imprescindible tenerlo en su arsenal.

La naturaleza misma de Vue.js te hace pensar en tu código de forma asincrónica para que puedas actualizar tus componentes correctamente, brindando así a tus usuarios una experiencia increíble.

Para obtener más información sobre el código asíncrono para Vue, puede consultar el Libro de cocina de Vue.js.