Sou novo em C# e estou tentando implementar tarefas assíncronas para várias chamadas de API, mas estou enfrentando um problema de como retornar a resposta da tarefa.
O código abaixo funciona perfeitamente para múltiplas chamadas de API:
public class ItemResponseJsonModel
{
public string ID { get; set; }
public string ResponseJSON { get; set; }
}
var listIDs = new List<string>
{
"ID1",
"ID2",
"ID3"
};
var postTasks = listIDs.Select(async p => new ItemResponseJsonModel { ID = p, ResponseJSON = await APIGetItemsByID(p) });
var posts = await System.Threading.Tasks.Task.WhenAll(postTasks);
foreach (var postContent in posts)
{
listResults.Add(postContent);
}
Task<string> APIGetItemsByID(string ID)
{
int page = 1;
string? API_Key = "The-API-Key"
Task<string> respJSON;
var client = new HttpClient();
string baseURL = $"https://API_URL/api/Items?pageSize=1000&Page={page}&id=";
client.DefaultRequestHeaders.Add("Authorization", "Basic " + API_Key);
respJSON = client.GetStringAsync(baseURL + ID);
return respJSON;
}
Agora estou me deparando com a situação de que cada ID pode ter várias páginas de resultados. A última página sempre retorna "[]", o que significa que não há dados, então implementei o loop Do/While abaixo para obter todas as respostas para cada ID. Este código abaixo funciona, mas é lento. Por favor, deixe-me saber se ele pode ser aprovado.
async Task<string> APIGetItemsByID(string ID)
{
int page = 1;
string? API_Key = "The-API-Key"
string respJSON = string.Empty;
string respContent;
do
{
var client = new HttpClient();
string baseURL = $"https://API_URL/api/Items?pageSize=1000&Page={page}&id=";
client.DefaultRequestHeaders.Add("Authorization", "Basic " + API_Key);
respContent = client.GetStringAsync(baseURL + ID);
if (respContent != "[]") {
respJSON += respContent;
}
page++;
} while (respContent != "[]" && page < 10);
return respJSON;
}
Qualquer ajuda é bem-vinda.
Se você quiser implementar paginação em suas chamadas de API, sua abordagem atual geralmente é boa, mas há várias melhorias que você pode fazer.
Primeiro, você está criando uma nova
HttpClient
instância dentro do seuAPIGetItemsByID
método, que está sendo chamado dentro de um loop. Isso não é recomendado. Cada vez que você cria um novoHttpClient
, ele abre uma nova conexão de socket sob o capô. Criar instâncias repetidamente em um loop pode esgotar rapidamente os recursos do sistema. Além disso, estabelecer novas conexões TCP repetidamente é mais lento do que reutilizar uma existente.Uma abordagem melhor é criar e reutilizar uma única
HttpClient
instância, especialmente dentro de loops ou para operações de alta frequência. No meu exemplo, instancio oHttpClient
fora do loop e o passo para seuAPIGetItemsByID
método.Você também está configurando
DefaultRequestHeaders
em seuHttpClient
. Os cabeçalhos definidos aqui se aplicam a todas as solicitações, então não há necessidade de adicioná-los a mensagens de solicitação individuais. Tenha em mente, no entanto, que você deve evitar modificarDefaultRequestHeaders
se houver solicitações pendentes, pois isso pode levar a um comportamento imprevisível.No seu
do-while
loop, você está verificando se a resposta é um array vazio. Isso funciona, mas para melhor legibilidade e clareza, você pode considerar sair explicitamente do loop quando uma resposta vazia for recebida.Por fim, como mencionado nos comentários, você está concatenando dados de resposta que vêm na forma de arrays. Se você simplesmente anexar arrays JSON como strings, você pode acabar com uma estrutura JSON inválida como
"[...][...]"
. Em vez disso, você deve analisar os arrays JSON e mesclar o conteúdo do array programaticamente. Isso garante que você está trabalhando com JSON válido e torna o processamento posterior muito mais fácil.Aqui estão minhas melhorias: