Introducción

Como Vue no es un framework completo como Angular, no te viene con una manera estándar de crear peticiones HTTP por lo que deja al usuario que use la manera que más le guste. Usualmente se suele usar axios que es como el fetch de javascript pero más cómo de usar.

Si ya conocías axios mucho de lo vas a leer ya te sonará porque se usa de la misma manera que en otros frameworks, aunque en esta guía también enseñaré como implementarlo con Vue. Pero antes veamos qué son las peticiones HTTP por si no las conocías de antes.

Las peticiones HTTP sirven para hacer llamadas al servidor. Cuando abres una página web el navegador se encarga de realizar peticiones HTTP al servidor para que éste le mande la página a renderizar. Además de para servir estáticos (html, css, javascript, imágenes, etc) también se suele usar para consumir y generar contenido de forma dinámica, es decir, contenido que normalmente se almacena en bases de datos como usuarios, posts, etc.

En los servidores se suelen crear lo que se conoce como API REST. Una API es un conjunto de endpoints o rutas preparadas para recibir peticiones HTTP. Las peticiones HTTP pueden ser de varios tipos:

  • GET: Simplemente devuelven información.
  • POST: A estos endpoints se envía información normalmente para crear o ejecutar acciones sobre recursos en bases de datos.
  • PUT: Se envía información al endpoint y se modifica en base de datos un recurso.
  • DELETE: Para borrar recursos del servidor.

Explicación de arriba de los métodos HTTP

Entonces, en este artículo nos vamos a conectar a una API con exios en Vue. Si te quieres hacer tu mismo la API, te recomiendo este artículo para que la hagas en Express JS. https://www.callicoder.com/node-js-express-mongodb-restful-crud-api-tutorial/

Pero. si solo quieres apreder y no quieres hacer una API, puedes usar esta de ejemplo que será la que usaré yo para esta guía.

https://jsonplaceholder.typicode.com/

Axios. Conexión a un backend

Bien, lo primero que tienes que hacer instalar axios en tu proyecto. Puedes mirar en las dependencias package.json si tienes instalado axios. Si no lo tienes puedes hacer lo siguiente:

npm install axios

Una vez instalado ya podemos realizar peticiones HTTP.

Lo primero que vamos a hacer es realizar una petición GET a la API de jsonplaceholder.

Peticiones GET a una API

Como ya vimos en el ciclo de vida de los componentes, una forma usual de realizar peticiones HTTP que alimenten la vista es desde el método created, vamos con ello:

<template>
  <div class="content"></div>
</template>

<script>
import axios from "axios";
export default {
  created() {
    axios.get("https://jsonplaceholder.typicode.com/todos/1").then((result) => {
      console.log(result.data);
    })
  }
};
</script>

<style scoped lang="scss">
</style>

Si creas este componente y lo importas en la vista, cuando cargue la página, en la consola del navegador podrás ver esto:

En la consola podrás ver que se imprime un objeto con los campos de la API

Si no conocías el funcionamiento de axios te explico un poco como va. Lo que tienes que hacer primero es importar axios en el componente. Una vez importado, y sin usar el this ya que no es una variable del data, llamas a axios con el método HTTP que necesites (get, post, put, delete, etc), en este caso el get.

Dentro del paréntesis pones dirección de la api a la que quieres llamar, aquí he puesto la de ejemplo. Como los métodos de axios son asíncronos y devuelven una promesa, tienes que usar el then para poder recoger el resultado. Dentro del then se suele usa una arrow function de javascript para definir el resultado.

Dentro de la variable result hay información sobre la petición y para recuperar el resultado tenemos que acceder al campo data.

Sabiendo esto, ya puedes guardar el resultado de la API en una variable del data para poder pintarla en la vista:

<template>
  <div class="content">
    <p>User ID: {{ result.userId }}</p>
    <p>Title: {{ result.title }}</p>
  </div>
</template>

<script>
import axios from "axios";
export default {
  data: () => ({
    result: null
  }),
  created() {
    axios.get("https://jsonplaceholder.typicode.com/todos/1").then((result) => {
      this.result = result.data;
    })
  }
};
</script>

<style scoped lang="scss">
</style>

Si haces esto Vue mostrará error en la consola porque intenta renderizar la vista antes de que la petición termine (nada más abrir la página la petición puede que esté cargando) y la variable result no tiene valor todavía (por tanto no puedes acceder a sus campos).

Una forma de resolver esto es simplemente con un if en la vista:

<template>
  <div v-if="result" class="content">
    <p>User ID: {{result.userId}}</p>
    <p>Title: {{result.title}}</p>
  </div>
</template>

Como Vue es reactivo, en cuanto termine de cargar la petición y por tanto la variable result tenga información, renderizará el resultado de la vista.

En la página aparece el userID y el name que son campos que vienen de la API

Peticiones DELETE

Las peticiones DELETE tienen la misma sintaxis que las del GET, tan solo tienes que cambiar el nombre del método:

created() {
  axios.delete("https://jsonplaceholder.typicode.com/todos/1");
}

En este caso como no queremos que la API nos devuelva nada cuando termine la petición no se pone el then. Si tu API devuelve algún tipo de información y la quieres para algo puedes usar el then.

Vamos ahora a ver cómo se pasa información a la API con las peticiones POST y PUT.

Peticiones POST, Y PUT

Las peticiones POST y PUT normalmente se usan pasando información desde el frontend a la API. Afortunadamente pasar información en una de estas llamadas es tan fácil como añadir un objeto o variable como segundo parámetro del paréntesis.

created() {
  let post = {
    title: 'foo',
    body: 'bar',
    userId: 1
  };
  axios.post("https://jsonplaceholder.typicode.com/posts", post).then((result) => {
    console.log(result);
  });
}

El PUT se hace exáctamente igual:

created() {
  let post = {
    title: 'foo',
    body: 'bar',
    userId: 1
  };
  axios.put("https://jsonplaceholder.typicode.com/posts/1", post).then((result) => {
    console.log(result);
  });
}

Async / await para las llamadas

Lo que vas a ver en este apartado es simplemente una sintaxis más clara para hacer las peticiones, pero el resultado será el mismo que los ejemplos vistos antes.

Con las versiones nuevas de javascript han metido una sintaxis nueva más clara para no tener que hacer el then.

async created() {
  let response = await axios.get("https://jsonplaceholder.typicode.com/todos/1");
  this.result = response.data;
}

Con esta sintaxis ya no vas a necesitar arrow functions ni nada de eso. Como digo es una sintaxis alternativa, y queda en tu mano si usarla o no, yo te la recomiendo porque es más clara de leer.

Para usarla, tienes que inicializar la variable en la que quieres recibir la respuesta al resultado de la petición HTTP con el await delante. Es importante saber que mientras en un método haya un await, no se va a ejecutar lo que haya debajo hasta que la petición termine. Además, tienes que poner delante del nombre del método en el que realices la petición la palabra async, de lo contrario no funcionará.

Otro detalle a tener en cuenta es que no se puede guardar directamente el resultado de la petición en una variable del data, es decir, esto NO funcionaría:

async created() {
  this.result = await axios.get("https://jsonplaceholder.typicode.com/todos/1").data;
}

Siempre tienes que guardar el resultado de la petición dentro de una variable intermedia.

Realizando varias peticiones a la vez con async await

Como hemos dicho, cuando se ejecute await el código que haya por debajo no se ejecutará hasta que la petición termine. Para resolver esto lo que recomiendo es que cada petición la hagas en un método async diferente y que desde el created llames a los métodos, de esta forma:

methods: {
  async getTodos() {
    let response = await axios.get("https://jsonplaceholder.typicode.com/todos/1");
    console.log(response.data);
  },
  async modifyPost() {
    let post = {
      title: 'foo',
      body: 'bar',
      userId: 1
    };
    let response = await axios.put("https://jsonplaceholder.typicode.com/posts/1", post)
    console.log(response.data);
  }
},
created() {
  this.getTodos();
  this.modifyPost();
}

Gestión de errores en las peticiones

Como axios devuelve una promesa para las peticiones, es sencillo saber si se ha producido un error. Para cuando utilizas las promesas con el then:

axios
  .get("https://jsonplaceholder.typicode.com/todos/1")
  .then(result => {
    this.result = result.data;
  })
  .catch(error => {
    console.log(error);
  });

Cuando se produzca un error en la petición se ejecutará el catch.

Para el caso de async / await lo que tienes que hacer es usar un try catch:

try {
  let response = await axios.get("https://jsonplaceholder.typicode.com/todos/1");
  this.result = response.data;
} catch (error) {
  console.log(error);
}

Para las dos formas una vez que tengas el error ya puedes hacer con él lo que quieras. Lo más sencillo es guardar el error en una variable del data para que se lo puedas mostrar el usuario.

Estructura que yo recomiendo

Lo que yo recomiendo es tener las peticiones HTTP en archivos aparte para que sean más mantenibles y las puedas reutilizar.

En mi caso lo que hago es crear una carpeta dentro de src llamada logic en la que creo un archivo .js por cada entidad. Para mí entidad es algo que tiene razón de ser por si misma, es decir, entidades por ejemplo son: users, posts, etc. Lo que haría en este caso sería crear un archivo users.js y posts.js, aunque tu caso puede ser otro.

Dentro de estos archivos lo que hago es crear una función por cada llamada a base de datos, devolviendo simplemente la petición. Veamos un ejemplo:

// src/todos.js
import axios from "axios";
const API = "https://jsonplaceholder.typicode.com/todos";

export default {
  get() {
    return axios.get(API);
  },
  create(todo) {
    return axios.post(API, todo);
  }
};

De tal forma que en el componente importas:

import todos from "@/logic/todos";

Y lo usas teniendo en cuenta que la llamada devuelve la petición de axios y por lo tanto tendrás que usar el then o el async / await

async created() {
  let response = await todos.get();
  console.log(response.data);
}

Con esta estructura si tienes que cambiar la API porque ahora se encuentra en otra dirección solo tendrás que cambiar estos archivos y se actualizarán todas las peticiones en las que se usen.

Conclusiones

Con lo que has aprendido hoy ya puedes conectare a una API, es decir, ahora se abre un mundo de posibilidades porque ahora puedes conectarte con un servidor y por tanto a una base de datos.

Si quieres practicar, con la API que hemos usado en este artículo, la de jsonplaceholder, puedes crear una web completa para mostrar, crear y editar todos (lista de tareas).

En el próximo capítulo usaremos lo que hemos aprendido hoy para crear un sistema de login y registro de usuarios. Stay tuned!.