3
votes

Traiter la même demande plusieurs fois

Je construis un jeu de quiz musical idiot pour apprendre. Je dois remplir ma vue avec de la musique associée à partir de deezer api .

Ce dont j'ai besoin:

  1. Obtenir un genre aléatoire
  2. Obtenez 5 artistes de ce genre (identifiant + nom)
  3. Obtenez 1 musique de chaque artiste (nom + aperçu du lien)

Donc, j'ai trouvé ma voie a > jusqu'à l'étape 3

Mais je ne trouve pas comment envoyer correctement la même demande 4 fois (pour chaque artiste), et mes recherches ne m'ont rien donné jusqu'à présent

function deezer() {

    const reqGenero = new Request('https://api.deezer.com/genre');

    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('https://api.deezer.com/genre/' + 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('https://api.deezer.com/artist/' + ids + '/top'); 
            }
        })         
        .catch(error => {
            console.error(error);
        });      
}


0 commentaires

4 Réponses :


1
votes

Vous pouvez créer 4 requêtes et attendre qu'elles soient toutes terminées , en utilisant Promise # all .

.then(artistas => {
  /* 1 música de 4 artistas */
  const artistasPromises = artistas.data.map(artista =>
    fetch("https://api.deezer.com/artist/" + artista.id + "/top").catch(
      err => ({ error: err })
    )
  );
  return Promise.all(artistasPromises);
}).then(musicList => {
  console.log(musicList);
});

Notez le catch () . Cela garantit que même si une extraction échoue, les autres résultats de l'extraction ne sont pas ignorés. Cela est dû à la façon dont Promise # all fonctionne. Ainsi, vous devez parcourir musicList et vérifier s'il existe un objet de la forme {error: / * error object * /} et l'ignorer lors du traitement de la liste.


0 commentaires

1
votes

Vous pouvez remplacer l'instruction

const fetchResults = [];    
artistasIds.forEach(function(ids){  
  fetchResults.push(fetch('https://api.deezer.com/artist/' + ids + '/top'));
});
return Promise.all(fetchResults);

par

// CAN I SEND THIS REQUEST 4 TIMES?
return fetch('https://api.deezer.com/artist/' + ids + '/top'); 

dans puis condition vous obtiendrez un tableau de valeurs avec la meilleure musique de chaque artiste. Je n'ai pas vérifié avec l'API donnée, mais idéalement, cela devrait fonctionner.


0 commentaires

1
votes

Oui, vous pouvez faire 5 requêtes (pas 4 ses 0-4) et attendre que chacune se termine. Utilisez Array.prototype.map pour créer un tableau de demandes de promesses (préférez for- forEach et array.push)

et Promise.all d'attendre que toutes les promesses se terminent, ce qui renverra le tableau des réponses résolues, si aucun échec.

.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(`https://api.deezer.com/artist/${id}/top`));
  return Promise.all(requests);
  }
}) 


0 commentaires

1
votes

Si vous utilisez les promesses explicitement (voir ci-dessous pour les fonctions async ), je l'aborderais probablement comme ceci; voir les commentaires de *** pour l'explication:

// *** 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('https://api.deezer.com/genre');
    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', 'https://api.deezer.com/genre/' + 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', 'https://api.deezer.com/artist/' + entry.id + '/top')
    ));
}

Cela suppose que vous voulez utiliser les résultats dans deezer . Si vous voulez que deezer renvoie les résultats (une promesse des quatre chansons), alors:

// *** 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('https://api.deezer.com/genre');
    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', 'https://api.deezer.com/genre/' + 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', 'https://api.deezer.com/artist/' + entry.id + '/top')
            ));
        });
        // *** No `then` using the results here, no `catch`; let the caller handle it
}

Le async version de la fonction de ce second:

// *** 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('https://api.deezer.com/genre');
    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', 'https://api.deezer.com/genre/' + 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', 'https://api.deezer.com/artist/' + entry.id + '/top')
            ));
        })         
        .then(musica => {
            // *** Use musica here, it's an array of the music responses
        })
        .catch(error => {
            console.error(error);
        });      
}


2 commentaires

typo return fetch (... args) doit être return fetch (args) .


@AZ_ - Non, ça ne devrait pas. Si vous passez plus de deux arguments à fetchJson , nous voulons étaler le paramètre rest lors de l'appel de fetch .