Cada vez que tengamos la necesidad de realizar varias peticiones a una API, la mejor practica es usar Promise.all(), es una función que nos permite realizar varias peticiones en paralelo, nos resulta bastante útil para mejor la rapidez de carga.
Introducción a Next.JS
¿Dónde aprender Next.js actualizado?
¿Qué es Next.JS?
Creando nuestra primera página
Styled JSX
Server Side Rendering
Aprende qué es Server Side Rendering
Intro a getInitialProps
Utilizando el componente Link
Recibiendo Parámetros
Performance de Get Initial Props
Vista de Podcasts
Componentes Reutilizables
Creando componentes en React
Reorganizar la vista de podcasts
Navegación Avanzada
Gestionando Errores
Personalizando errores
¿Cómo diseñar URLs?
Configurando Next Routes
Implementando Next Routes
Vistas Híbridas
Implementar el Modal
Agregando un loader
Publicando nuestra app
Mejores prácticas en Github
Publicar la app con now
Conclusiones del curso
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Al utilizar await en cada fetch al traer los datos desde la API nos evitamos el callback hell, pero estamos haciendo que el usuario tenga que esperar cerca de un segundo y medio hasta que se completen secuencialmente las tres request.
En esta clase veremos cómo con Promise.all() solucionamos este problema de performance al paralelizar nuestras request.
Aportes 14
Preguntas 3
Cada vez que tengamos la necesidad de realizar varias peticiones a una API, la mejor practica es usar Promise.all(), es una función que nos permite realizar varias peticiones en paralelo, nos resulta bastante útil para mejor la rapidez de carga.
Si quieren hacer tanto la request como la parte de pasar a JSON en la misma parte donde se hacen todas juntas, pueden usar .then()
Personalmente a mí me gusta más así para no declarar tantas variables ^^
static async getInitialProps({query}){
let idChannel = query.id
let [reqChannel, reqSeries, reqAudios] = await Promise.all([
fetch(`https://api.audioboom.com/channels/${idChannel}`).then((response) => response.json()),
fetch(`https://api.audioboom.com/channels/${idChannel}/child_channels`).then((response) => response.json()),
fetch(`https://api.audioboom.com/channels/${idChannel}/audio_clips`).then((response) => response.json())
])
let channel = reqChannel.body.channel;
let series = reqSeries.body.channels;
let audioClips = reqAudios.body.audio_clips;
return { channel, audioClips, series }
}```
Bueeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee e esto esta genial!
static async getInitialProps ({ query: { id }}) {
const [reqChannel, reqAudio, reqSeries] = await Promise.all([
fetch(`https://api.audioboom.com/channels/${id}`),
fetch(`https://api.audioboom.com/channels/${id}/audio_clips`),
fetch(`https://api.audioboom.com/channels/${id}/child_channels`)
])
const [
{ body: { channel }},
{ body: { audio_clips: audioClips }},
{ body: { channels: series }}
] = await Promise.all([
reqChannel.json(),
reqAudio.json(),
reqSeries.json()
])
return {
channel,
audioClips,
series
}
}
Usando aún mas la desestructuración y cachando errores
static async getInitialProps({ query: { id } }) {
try {
const [reqChannel, reqAudios, reqChilds] = await Promise.all([
fetch(`https://api.audioboom.com/channels/${id}`),
fetch(`https://api.audioboom.com/channels/${id}/audio_clips`),
fetch(`https://api.audioboom.com/channels/${id}/child_channels`),
]);
const { body: { channel } } = await reqChannel.json();
const { body: { audio_clips } } = await reqAudios.json();
const { body: { channels } } = await reqChilds.json();
return { channel, audio_clips, channels };
} catch ({ message }) {
return (message);
}
}
No me gusto esta clase, se salta muchas cosas que en un principio son difíciles de entender
Porqué usamos let [req1, re2]
en vez de const [req1, req2]
?
Probé con const
y me funciona muy bien. Por favor alguien digame que diferencia puede haber entre uno y otro.
Tener en cuenta que puede romperse:
Si alguna de las promesas pasadas en el argumento iterable falla, la promesa all es rechazada inmediatamente con el valor de la promesa que fué rechazada, descartando todas las demás promesas hayan sido o no cumplidas. - MDN
Gracias a esto si alguno falla continua la ejecución de las demás.
const [ requestChannel, requestClips, requestChilds ] = await Promise.all([
request.get(`/channels/${idChannel}`, '').catch(error => error),
request.get(`/channels/${idChannel}/audio_clips`, '').catch(error => error),
request.get(`/channels/${idChannel}/child_channels`, '').catch(error => error)
]);
Utilicé otro cliente HTTP para utilizar las llamadas al API, pero utilicen la Fetch del curso.
Usando getServerSideProps
y declarando funciones asíncronas, se puede tener un código más modulado:
Cada función asíncrona se encarga de obtener datos puntuales del canal.
async function getChannel(channelId) {
const request = await fetch(`https://api.audioboom.com/channels/${channelId}`);
const { body: { channel } } = await request.json();
return channel;
}
async function getAudioclips(channelId) {
const request = await fetch(`https://api.audioboom.com/channels/${channelId}/audio_clips`);
const { body: { audio_clips } } = await request.json();
return audio_clips;
}
async function getChildChannels(channelId) {
const request = await fetch(`https://api.audioboom.com/channels/${channelId}/child_channels`);
const { body: { channels } } = await request.json();
return channels;
}
export async function getServerSideProps({ query }) {
const [channel, audioClips, series] = await Promise.all([
getChannel(query.id),
getAudioclips(query.id),
getChildChannels(query.id),
]);
return {
props: { channel, audioClips, series },
};
}
Consulta como se deberia hacer el await si para el siguiente fecht necesita del anterior ya no servivio el all? ¿Qué metodo deberiamos utilizar?
Un poco mas corto
static async getInitialProps({ query }) {
let [reqChannel, reqAudioClips, reqSeries] = await Promise.all([
fetch(`https://api.audioboom.com/channels/${query.id}`),
fetch(`https://api.audioboom.com/channels/${query.id}/audio_clips`),
fetch(`https://api.audioboom.com/channels/${query.id}/child_channels`)
]);
let channel = (await reqChannel.json()).body.channel;
let audioClips = (await reqAudioClips.json()).body.audio_clips;
let series = (await reqSeries.json()).body.channels;
return {channel, audioClips, series}
}```
Aquí el código de ésta clase. Excelente tip del Promise.All()
export default class extends React.Component {
static async getInitialProps({ query }) {
let idChannel = query.id;
let [reqChannel, reqSeries, reqAudios] = await Promise.all([
//Mejora el performance de la App porque hace los request en paralelo
fetch(`https://api.audioboom.com/channels/${idChannel}`),
fetch(`https://api.audioboom.com/channels/${idChannel}/child_channels`),
fetch(`https://api.audioboom.com/channels/${idChannel}/audio_clips`)
]);
let dataChannel = await reqChannel.json();
let channel = dataChannel.body.channel;
let dataAudios = await reqAudios.json();
let audioClips = dataAudios.body.audio_clips;
let dataSeries = await reqSeries.json();
let series = dataSeries.body.channels;
return { channel, audioClips, series };
}
render() {
const { channel, audioClips, series } = this.props;
return (
<div>
<header>@viistorrr Podcasts</header>
<h1>{channel.title}</h1>
<h2>Ultimos Podcasts</h2>
{audioClips.map(clip => (
<div>{clip.title}</div>
))}
<h2>Series</h2>
{series.map(serie => (
<div>{serie.title}</div>
))}
<style jsx>{`
header {
color: #fff;
background: #8756ca;
padding: 15px;
text-align: center;
}
.channels {
display: grid;
grid-gap: 15px;
padding: 15px;
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
}
a.channel {
display: block;
margin-bottom: 0.5em;
color: #333;
text-decoration: none;
}
.channel img {
border-radius: 3px;
box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.15);
width: 100%;
}
h1 {
font-weight: 600;
padding: 15px;
}
h2 {
padding: 5px;
font-size: 0.9em;
font-weight: 600;
margin: 0;
text-align: center;
}
`}</style>
<style jsx global>{`
body {
margin: 0;
font-family: system-ui;
background: white;
}
`}</style>
</div>
);
}
}
Request paralelas a un api, mejora de performance
Si utilizan axios, no es necesario hacer la conversión a json:
Deben instalar primero axios e importarlo.
import axios from "axios";
//Capturamos la data de la api
let data= await axios.get("https://api.audioboom.com/channels/recommended");
//La respuesta es un objeto con la propiedad data donde viene todo como un json
return data.data
Asi puede implementarse axios en el getInitialProps
channel.getInitialProps = async ({ query }) => {
let idChannel = query.id;
let URL1 = `https://api.audioboom.com/channels/${idChannel}`
let URL2 = `https://api.audioboom.com/channels/${idChannel}/audio_clips`
let URL3 = `https://api.audioboom.com/channels/${idChannel}/child_channels`
let [ reqChannel, reqAudios, reqSeries ] = await Promise.all([ axios.get(URL1), axios.get(URL2), axios.get(URL3) ]);
const dataChannel = await reqChannel.data;
let channel = dataChannel.body.channel;
const dataAudios = await reqAudios.data;
let audioClips = dataAudios.body.audio_clips;
const dataSeries = await reqSeries.data;
let series = dataSeries.body.channels;
let response = { channel, audioClips, series }
return {...response}
}
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?