Handle Same Request Multiple Times
I'm Building a Silly Music Quiz Game for Learning. I Need to Populate My View with Related Music from Deezer Api. What I Need: Get a Random Genre Get 5 Artist...
I'm building a silly music quiz game for learning. I need to populate my view with related music from deezer api.
What I need:
- Get a random genre
- Get 5 artist from this genre (id + name)
- Get 1 music from each artist (name + link preview)
So, I found my way until step 3
But I can't find out how to properly send the same request 4 times (for each artist), and my reasearch gave me nothing so far
function deezer() {
const reqGenero = new Request(');
fetch(reqGenero)
.then(response => {
if (response.status === 200) {
return response.json();
} else {
throw new Error('Erro ao pegar gêneros');
}
})
.then(generos => {
/* pega genero aleatorio */
var generoId = generos.data[Math.floor(Math.random() * 10 + 1)].id;
//console.log('\ngenero... ' + generoId);
return fetch(' + generoId + '/artists')
})
.then(response => {
if (response.status === 200) {
return response.json();
} else {
throw new Error('Erro ao pegar artistas');
}
})
.then(artistas => {
/* 1 música de 4 artistas */
var artistasIds = [];
for(var i = 0; i <= 4; i++) {
artistasIds.push(artistas.data[i].id);
console.log('\nId: ' + artistasIds[i]);
// CAN I SEND THIS REQUEST 4 TIMES?
return fetch(' + ids + '/top');
}
})
.catch(error => {
console.error(error);
});
}
*Pleade let me know if I'm doing something really wrong
4 Answers
If using promises explicitly (see below for async functions), I'd probably approach it like this; see *** comments for explanation:
// *** Give yourself a helper function so you don't repeat this logic over and over
function fetchJson(errmsg, ...args) {
return fetch(...args)
.then(response => {
if (!response.ok) { // *** .ok is simpler than .status == 200
throw new Error(errmsg);
}
return response.json();
});
}
function deezer() {
// *** Not sure why you're using Request here?
const reqGenero = new Request(');
fetchJson('Erro ao pegar gêneros', reqGenero)
.then(generos => {
/* pega genero aleatorio */
var generoId = generos.data[Math.floor(Math.random() * 10 + 1)].id;
//console.log('\ngenero... ' + generoId);
return fetchJson('Erro ao pegar artistas', ' + generoId + '/artists')
})
.then(artistas => {
/* 1 música de 4 artistas */
// *** Use Promise.all to wait for the four responses
return Promise.all(artistas.data.slice(0, 4).map(
entry => fetchJson('Erro ao pegar música', ' + entry.id + '/top')
));
})
.then(musica => {
// *** Use musica here, it's an array of the music responses
})
.catch(error => {
console.error(error);
});
}
That's assuming you want to use the results in deezer. If you want deezer to return the results (a promise of the four songs), then:
// *** Give yourself a helper function so you don't repeat this logic over and over
function fetchJson(errmsg, ...args) {
return fetch(...args)
.then(response => {
if (!response.ok) { // *** .ok is simpler than .status == 200
throw new Error(errmsg);
}
return response.json();
});
}
function deezer() {
const reqGenero = new Request(');
return fetchJson('Erro ao pegar gêneros', reqGenero) // *** Note the return
.then(generos => {
/* pega genero aleatorio */
var generoId = generos.data[Math.floor(Math.random() * 10 + 1)].id;
//console.log('\ngenero... ' + generoId);
return fetchJson('Erro ao pegar artistas', ' + generoId + '/artists')
})
.then(artistas => {
/* 1 música de 4 artistas */
// *** Use Promise.all to wait for the four responses
return Promise.all(artistas.data.slice(0, 4).map(
entry => fetchJson('Erro ao pegar música', ' + entry.id + '/top')
));
});
// *** No `then` using the results here, no `catch`; let the caller handle it
}
The async function version of that second one:
// *** Give yourself a helper function so you don't repeat this logic over and over
async function fetchJson(errmsg, ...args) {
const response = await fetch(...args)
if (!response.ok) { // *** .ok is simpler than .status == 200
throw new Error(errmsg);
}
return response.json();
}
async function deezer() {
const reqGenero = new Request(');
const generos = await fetchJson('Erro ao pegar gêneros', reqGenero);
var generoId = generos.data[Math.floor(Math.random() * 10 + 1)].id;
//console.log('\ngenero... ' + generoId);
const artistas = await fetchJson('Erro ao pegar artistas', ' + generoId + '/artists');
/* 1 música de 4 artistas */
// *** Use Promise.all to wait for the four responses
return Promise.all(artistas.data.slice(0, 4).map(
entry => fetchJson('Erro ao pegar música', ' + entry.id + '/top')
));
}
You can replace the statement
// CAN I SEND THIS REQUEST 4 TIMES?
return fetch(' + ids + '/top');
with
const fetchResults = [];
artistasIds.forEach(function(ids){
fetchResults.push(fetch(' + ids + '/top'));
});
return Promise.all(fetchResults);
in then condition you'll get an array of values with top music from each artist. I haven't checked with the given API, but ideally it should work.
You can create 4 requests and wait for all of them to complete, using Promise#all.
.then(artistas => {
/* 1 música de 4 artistas */
const artistasPromises = artistas.data.map(artista =>
fetch("" + artista.id + "/top").catch(
err => ({ error: err })
)
);
return Promise.all(artistasPromises);
}).then(musicList => {
console.log(musicList);
});
Notice the catch(). This makes sure that even if a fetch fails, the other fetch results are not ignored. This is because of the way Promise#all works. So, you need to iterate over musicList and check if there is any object of the shape { error: /* error object */ } and ignore that while processing the list.
Yes you can make 5 requests (not 4 its 0-4) and wait for each to complete. Use Array.prototype.map to create an array of request promises.(prefer over for- forEach and array.push)
and Promise.all to wait for all the promises to get complete, which will return the array of resolved responses, if no failures.
.then(artistas => {
/* 1 música de 4 artistas */
var artistasIds = [];
let ids = artistas.data.map(artist => artist.id).slice(0, 4);
requests = ids.map(id => fetch(`));
return Promise.all(requests);
}
})