Esclarecimento sobre como o IAsyncEnumerable funciona com a API da Web do ASP.NET

9

Encontrei um comportamento interessante ao explorar IAsyncEnumerable em um projeto de API da Web do ASP.NET. Considere os seguintes exemplos de código:

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

A amostra 1 (matriz int) retorna {}como resultado JSON.

A amostra 2 retorna o resultado esperado ["0","1","2","3","4","5","6","7","8","9"]. No entanto, toda a matriz JSON é retornada ao mesmo tempo após 10 segundos de espera. Ele não deve ser retornado quando os dados estiverem disponíveis conforme o esperado da interface IAsyncEnumerable? Ou existe alguma maneira específica de que essa API da Web deva ser consumida?

Ravi M Patel
fonte
4
Ele não deve ser retornado quando os dados estiverem disponíveis conforme o esperado da interface IAsyncEnumerable? ... e ele faz ... mas para serializador JSON
Selvin
11
e Amostra 1 .... parece ser um bug de tipo não de referência (se você mudar IAsyncEnumerable<int>para IAsyncEnumerable<object>- ele deve funcionar, mas depois há um boxe envolvidos)
Selvin
@ Selvin, você poderia elaborar? Ou aponte para um exemplo de código? Eu tentei consumir este API com C # cliente, o resultado é o mesmo, tem que esperar por 10 segundos ...
Ravi M Patel
tem que esperar 10 segundos é obviosu ... serialização está no lado do servidor e não é assíncrona ... elaborado sobre o que?
Selvin
11
o bug está aqui ... obviamente, é por isso que?
Selvin

Respostas:

3

Uma chamada de API da Web não retornará json parcial a cada segundo. É o serializador json que precisa esperar 10 x 1 segundo (ou o código que chama o serializador json, que faz parte do ASP .NET). Depois que o código da estrutura e o serializador obtiverem todos os dados, eles serão serializados servidos - como uma única resposta - ao cliente.

Nos tipos de retorno de ação do Controller na API da web do ASP.NET Core , podemos ler:

No ASP.NET Core 3.0 e posterior, retornando IAsyncEnumerable de uma ação:

  • Não resulta mais em iteração síncrona.
  • Torna-se tão eficiente quanto retornar IEnumerable.

O ASP.NET Core 3.0 e versões posteriores armazenam em buffer o resultado da ação a seguir antes de fornecê-lo ao serializador:

public IEnumerable<Product> GetOnSaleProducts() =>
  _context.Products.Where(p => p.IsOnSale);
timtim
fonte