Creamos un archivo llamado Launches.astro con el siguiente contenido:
1)const res = await fetch('https://api.spacexdata.com/v5/launches/query')
-> Primero realizamos la solicitud HTTP usando la funcion fetch. La respuesta es un objeto ‘response’ que contiene metodos y propiedades. Necesitamos convertirlo a JSON para poder trabajarlo.
2)const data = await res.json()
-> Convertimos la respuesta a un objeto JSON.
3) const data = JSON.stringify(data)
-> Dicho objeto JSON lo convertimos en una cadena JSON.
4) Dicha cadena JSON la parseamos en https://app.quicktype.io/ para Typescript, lo cual nos permitira realizar la asercion de tipo mediante la cual informamos al compilador de Typescript que tipos esperamos en cada variable. Creamos el archivo de typescript “api.ts” en la carpeta types y lo importamos como tipo en el componente Astro que estamos utilizando:import {type ApiSpaceXResponse, type Doc} from "../types/api";
No nos olvidemos de incluir todos los tipos necesarios (como type Doc), caso contrario el IDE no autocompletara los valores si nos olvidamos de alguno.
Contenido (de ejemplo) de types/api.ts:
export type ApiSpaceXResponse = {
docs: Doc[];
totalDocs: number;
}
export type Doc = {
fairings: Fairings | null;
links: Links;
window: number;
rocket: Rocket;
success: boolean;
failures: Failure[];
}
5) Una vez obtenemos los tipos (y su posterior guardado e importacion mediante la linea indicada en el paso 4), dejamos la linea 2 y 3 de la siguiente manera:const {docs: launches} = (await res.json()) as apiSpaceXResponse;
La asercion de tipo “as apiSpaceXResponse” indica al compilador de Typescript que trate al objeto JSON como si tendria la estructa y los tipos indicados enApiSpaceXResponse
. La asercion de tipo no verifica ni valida la estructura del objeto JSON en tiempo de ejecucion pero nos permite utilizar la autocompletacion de Typescript.
Por otro lado, desestructuramos el objeto JSON, tomamos la propiedad “docs” y la guardamos en una variable llamada “launches” {docs: launches}
para poder utilizarla con mejor significado, el cual se trata de un array de objetos JSON:
const {docs: launches} = (await res.json()) as apiSpaceXResponse;
------
<div class="grid gap-8 sm:grid-cols-2 lg:grid-cols-3">
{
launches.map((launch) => (
<h2>ID launch: {launch.id}</h2>
</h2>
))
}
</div>
Hasta aqui tenemos la llamada a la API y su posterior captura de datos funcional. Ahora vamos a optimizar el codigo, colocando la llamada a la API en un nuevo archivo Typescript en /components/services/spacex.ts
En este archivo el unico cambio que realizamos es englobar la llamada a la API en una funcion asincrona y retornar el objeto JSON al final:
import type {ApiSpaceXResponse} from "../../types/api.ts";
export const getLatestLaunches = async () => {
const res = await fetch('https://api.spacexdata.com/v5/launches/query', {
method: 'POST',
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
query: {},
options: {
sort: {
date_unix: "asc",
},
limit: 55,
},
}),
})
const { docs : launches } = (await res.json()) as ApiSpaceXResponse;
return launches;
}
Mientras que en Launches.astro incorporamos la llamada al servicio y guardamos en variable el arreglo retornado:
---
import {getLatestLaunches} from "./services/spacex";
const launches = await getLatestLaunches();
---
<div class="grid gap-8 sm:grid-cols-2 lg:grid-cols-3">
{
launches.map(
({id, links, details, flight_number : flightNumber,success}) => (
<CardLaunch
id={id}
img={links.patch.small}
details={details}
flightNumber={flightNumber}
success={success}
/>
))
}
</div>