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:

  1. Get a random genre
  2. Get 5 artist from this genre (id + name)
  3. 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') )); } 
2

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); } }) 

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.