Páginas

lunes, 6 de enero de 2020

Javascript: Ejemplo de llamada síncrona al api fetch


Objetivo

En este post se explica cómo utilizar el API Fetch para obtener un fichero json. Lo interesante de este ejemplo es cómo hay que codificar las funciones, para que el orden en que se ejecutan las sentencias javascript sea el adecuado y de esta forma evitar asincronías no deseadas.

El API fetch es asíncrono, esto quiere decir que cuando se ejecuta, se lanza la petición y la ejecución continúa sin esperar a que el resultado haya sido recuperado. Si esta forma asíncrona de funcionamiento no se tiene en cuenta, no hay garantía de obtener la respuesta adecuada. Es decir, si el proceso a realizar depende de los datos recibidos no se puede realizar dicho proceso hasta que se haya recibido la respuesta.

Punto de partida

En este ejemplo se usa el API REST  https://jsonplaceholder.typicode.com/ , es un API displonible de forma gratuita para poder realizar pruebas. Para crear la infraestructura de este ejemplo, se inicia un proyecto node express (https://expressjs.com/en/starter/hello-world.html). Este framework se usa para construir la aplicación que arranca un servidor que resuelve peticiones http por el puerto 3000.

Ejemplo

Para ejecutar la prueba se usa el comando "node app.js". Este comando arranca la aplicación web que escucha en el puerto 3000

node app.js
Example app listening on port 3000!

Una vez arracada, abrir una ventana del browser y escribir http://localhost:3000/damepost
Siguiendo la estructura de un proyecto node express, para dar respuesta a esta petición se crea el módulo app.js. Este módulo es el que arranca la aplicación y tiene codificada la ruta “/damepost”. Ver a continuación app.get. Aquí es donde se indica lo que la aplicación tiene que hacer cuando se escribe la petición http http://localhost:3000/damepost

app.js

constexpress = require('express')
const app = express()
const port = 3000
const f = require('./functionsRefactored.js')

app.get('/damepost'async (reqres=> res.send(await f.hagoFetch())) 

app.listen(port, () => console.log(`Example app listening on port ${port}!`))

Cuando se realiza la petición http://localhost:3000/damepost, la aplicación llama a la función

 async (req, res) => res.send(await f.hagoFetch())

Esta arrow function llama a hagoFetch(). Esta función está exportada desde el módulo functionsRefactored.js que se muestra a continuación.

functionsRefactored.js

fetch = require('node-fetch');

async function hagoFetch() {
  const response = await fetch('https://jsonplaceholder.typicode.com/posts/1')
    .catch(error =>{console.error(error)})
  const json = await response.json();
  return json
}

exports.hagoFetch=hagoFetch;


En hagoFecth se solicita el fichero json que devuelve todos los posts del usuario cuyo código de identificación es 1. La solicitud se hace con await, es decir el control de ejecución para y espera hasta que response.json() termina para continuar. 
 
Una vez que se dispone de response, se obtiene el fichero json con el método json(). Este método también se invoca de forma síncrona con await. Por lo tanto, hagoFetch() no retorna la constante json hasta que no contiene todos los datos.

Resumen

Convertir en síncrona la petición fetch, se ha conseguido mediante dos llamadas con await.

  1.  await fetch(….) no devuelve la constante response hasta que  fetch ha terminado.  
  2.  await response.json() no devuelve la constante json hasta que la función ha terminado.

Para poder hacer await dentro de la función  hagoFetch() se ha tenido que declarar como función async. A su vez la llamada a la función hagoFetch en app.js se hace con await. Para poder hacer await la arrow function de app.get para la ruta /damepost está declarada como async.

Espero que esto sea de utilidad para alguien por ahí que se esté pegando con fetch y la asincronía. Si tenéis alguna duda dejad un comentario.

1 comentario: