简体   繁体   English

多次处理相同的请求

[英]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 . 我需要用来自deezer api的相关音乐来填充我的观点。

What I need: 我需要的:

  1. Get a random genre 获得随机类型
  2. Get 5 artist from this genre (id + name) 从这个类型中获得5位艺术家(id + name)
  3. Get 1 music from each artist (name + link preview) 每位艺术家获得1首音乐(名称+链接预览)

So, I found my way until step 3 所以, 我找到了自己的方式直到第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 但我无法找到如何正确发送相同的请求4次(对于每个艺术家),我的研究报告给了我什么

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

*Pleade let me know if I'm doing something really wrong *如果我做错了什么,请告诉我

If using promises explicitly (see below for async functions), I'd probably approach it like this; 如果明确使用promises(参见下面的async函数),我可能会这样做; 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('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);
        });      
}

That's assuming you want to use the results in deezer . 假设你想在deezer使用结果。 If you want deezer to return the results (a promise of the four songs), then: 如果你想让deezer 返回结果(四首歌的承诺),那么:

// *** 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
}

The async function version of that second one: 第二个的async函数版本:

// *** 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')
    ));
}

You can create 4 requests and wait for all of them to complete , using Promise#all . 您可以使用Promise#all创建4个请求并等待所有请求完成

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

Notice the catch() . 注意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. 这是因为Promise#的所有方式有效。 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. 因此,您需要迭代musicList并检查是否存在形状的任何对象{ error: /* error object */ }并在处理列表时忽略它。

You can replace the statement 您可以替换该语句

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

with

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

in then condition you'll get an array of values with top music from each artist. then条件下,你会得到的值从每个艺术家的顶级音乐的数组。 I haven't checked with the given API, but ideally it should work. 我没有检查给定的API,但理想情况下它应该工作。

Yes you can make 5 requests (not 4 its 0-4) and wait for each to complete. 是的,您可以发出5个请求(不是4个0-4)并等待每个请求完成。 Use Array.prototype.map to create an array of request promises.(prefer over for- forEach and array.push) 使用Array.prototype.map创建一个请求承诺数组。(首选for-forEach和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. Promise.all等待所有的promises完成,如果没有失败,它将返回已解析的响应数组。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM