J'ai rencontré un comportement intéressant lors de l'exploration de IAsyncEnumerable dans un projet d'API Web ASP.NET. Considérez les exemples de code suivants:
// Code Sample 1
[HttpGet]
public async IAsyncEnumerable<int> GetAsync()
{
for (int i = 0; i < 10; i++)
{
await Task.Delay(1000);
yield return i;
}
}
// Code Sample 2
[HttpGet]
public async IAsyncEnumerable<string> GetAsync()
{
for (int i = 0; i < 10; i++)
{
await Task.Delay(1000);
yield return i.ToString();
}
}
L'échantillon 1 (tableau int) renvoie {}
comme résultat JSON.
L'échantillon 2 renvoie le résultat attendu ["0","1","2","3","4","5","6","7","8","9"]
. Cependant, l'intégralité du tableau JSON est retourné en une seule fois après 10 secondes d'attente. Ne doit-il pas être renvoyé lorsque les données deviennent disponibles comme prévu à partir de l'interface IAsyncEnumerable? Ou existe-t-il un moyen spécifique de consommer cette API Web?
Un appel web api ne renverra pas json partiel toutes les secondes. C'est le sérialiseur json qui doit attendre 10x1seconde (ou le code qui appelle le sérialiseur json, qui fait partie de ASP .NET). Une fois que le code de framework et le sérialiseur auront obtenu toutes les données, il être sérialisé servi - en tant que réponse unique - au client.
Dans types de retour d'action du contrôleur dans l'API Web ASP.NET Core , nous pouvons lire:
Dans ASP.NET Core 3.0 et versions ultérieures, retour de IAsyncEnumerable à partir d'une action:
- N'entraîne plus d'itération synchrone.
- Devient aussi efficace que renvoyant IEnumerable.
ASP.NET Core 3.0 et versions ultérieures mettent en mémoire tampon le résultat de l'action suivante avant de le fournir au sérialiseur:
public IEnumerable<Product> GetOnSaleProducts() => _context.Products.Where(p => p.IsOnSale);