Wyjaśnienie, w jaki sposób IAsyncEnumerable współpracuje z ASP.NET Web API

9

Spotkałem interesujące zachowanie podczas eksploracji IAsyncEnumerable w projekcie ASP.NET Web API. Rozważ następujące przykłady kodu:

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

Próbka 1 (tablica int) zwraca {}jako wynik JSON.

Próbka 2 zwraca oczekiwany wynik ["0","1","2","3","4","5","6","7","8","9"]. Jednak cała tablica JSON jest zwracana jednocześnie po 10 sekundach oczekiwania. Czy nie należy zwrócić, ponieważ dane stają się dostępne zgodnie z oczekiwaniami z interfejsu IAsyncEnumerable? Czy jest jakiś konkretny sposób, w jaki należy korzystać z tego interfejsu API?

Ravi M. Patel
źródło
4
Czy nie należy zwrócić, ponieważ dane stają się dostępne zgodnie z oczekiwaniami z interfejsu IAsyncEnumerable? ... i tak jest ... ale dla serializatora json
Selvin
1
i Próbka 1 .... wydaje się być błędem dla typu bez odniesienia (jeśli zmienisz IAsyncEnumerable<int>na IAsyncEnumerable<object>- powinno działać, ale wtedy występuje boks)
Selvin
@Selvin, czy mógłbyś opracować? Lub wskaż próbkę kodu? Próbowałem skonsumować ten interfejs API z klientem C #, wynik jest taki sam, muszę czekać 10 sekund ...
Ravi M Patel
muszę czekać 10 sekund, to obviosu ... serializacja jest po stronie serwera i nie jest asynchroniczna ... opracowana na temat czego?
Selvin,
1
błąd jest tutaj ... oczywiście dlatego
Selvin

Odpowiedzi:

3

Wywołanie interfejsu API sieci Web nie zwróci częściowego JSON co sekundę. To serializator json musi czekać 10x1 sekund (lub kod wywołujący serializator json, który jest częścią ASP .NET). Gdy kod frameworku i serializator otrzymają wszystkie dane, zostaną one zserializowane dostarczone - jako pojedyncza odpowiedź - do klienta.

W typach akcji kontrolera zwracanych w interfejsie API sieci Web platformy ASP.NET Core możemy przeczytać:

W programie ASP.NET Core 3.0 i nowszych zwracanie IAsyncEnumerable z działania:

  • Nie powoduje już synchronicznej iteracji.
  • Staje się tak wydajny, jak zwracanie IEnumerable.

Program ASP.NET Core 3.0 i nowsze wersje buforują wynik następującej akcji przed przekazaniem go do serializatora:

public IEnumerable<Product> GetOnSaleProducts() =>
  _context.Products.Where(p => p.IsOnSale);
tymtam
źródło