What is IAsyncEnumerable
IAsyncEnumerable<T>
It is an interface in .NET that represents asynchronous data flow.
It allows you to get data items asynchronously one by one, rather than loading all data into memory at once. This reduces memory usage, especially when processing large amounts of data.
andIEnumerable<T>
different,IEnumerable<T>
It is synchronous and requires all data to be loaded before it is returned.
andIAsyncEnumerable<T>
It is asynchronous and supports gradual loading when the data stream is requested. It is suitable for processing data obtained asynchronously from sources such as databases or networks.
Example:
public async IAsyncEnumerable<int> GetNumbersAsync()
{
for (int i = 0; i < 10; i++)
{
await (100); // Simulate asynchronous operations
yield return i;
}
}
benefit
Reduce memory usage:IAsyncEnumerable<T>
Loading data step by step avoids the need to load all data into memory at once. For querying large data volumes, memory pressure can be significantly reduced.
Improve response performance: In WebAPI, returnIAsyncEnumerable<T>
This allows the client to start processing immediately when obtaining part of the data without waiting for all the data to be loaded. This makes the response time shorter and improves the user experience.
Avoid blocking operations:useasync/await
This allows WebAPI to not be slowed down by synchronization blocking operations, and can better handle concurrent requests.
Take WebAPI + EFCore as an example
Suppose we need to query a large number of records from the database through the Entity Framework Core.
If we load all the data at once, it may cause excessive memory usage and even affect performance. useIAsyncEnumerable<T>
, we can get data one by one.
Sample code:
public class ProductController : ControllerBase
{
private readonly ApplicationDbContext _context;
public ProductController(ApplicationDbContext context)
{
_context = context;
}
[HttpGet("products")]
public async IAsyncEnumerable<Product> GetProductsAsync()
{
await foreach (var product in _context.())
{
yield return product;
}
}
}
In this example,AsAsyncEnumerable()
Method willDbSet<Product>
Convert to an asynchronous data stream,await foreach
Loops asynchronously from the database one by one to avoid excessive memory usage.
Take WebAPI + HTTPClient as an example
In the WebAPI, you may need to call other services or external APIs to get the data. useIAsyncEnumerable<T>
The data returned by the call can be loaded gradually, avoiding waiting for the entire request to complete before returning.
Sample code:
public class ExternalApiController : ControllerBase
{
private readonly HttpClient _httpClient;
public ExternalApiController(HttpClient httpClient)
{
_httpClient = httpClient;
}
[HttpGet("external-data")]
public async IAsyncEnumerable<string> GetExternalDataAsync()
{
var response = await _httpClient.GetAsync("/data");
();
var stream = await ();
using (var reader = new StreamReader(stream))
{
string? line;
while ((line = await ()) != null)
{
yield return line;
}
}
}
}
In this example, we request external API data via HTTPClient and useIAsyncEnumerable<string>
Returns each row of data, allowing the client to process the data step by step without waiting for all data to be loaded.
How to handle the clientIAsyncEnumerable<T>
Client receivedIAsyncEnumerable<T>
After the data flow, an asynchronous iterator can be usedawait foreach
to process the data step by step.
This allows data to be processed and displayed in a timely manner during the gradual transmission of the data stream without waiting for all data to be loaded.
C# client code:
public class ProductClient
{
private readonly HttpClient _httpClient;
public ProductClient(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task GetProductsAsync()
{
var response = await _httpClient.GetAsync("/products");
();
await foreach (var product in <IAsyncEnumerable<Product>>())
{
();
}
}
}
JavaScript client processing:
In JavaScript, clients can usefetch
APIs and streams to process data step by step. The data stream returned by WebAPI can pass()
Come to read and consume step by step.
async function fetchProducts() {
const response = await fetch('/products');
const reader = ();
const decoder = new TextDecoder();
let done = false;
let value = '';
while (!done) {
const { done: chunkDone, value: chunk } = await ();
done = chunkDone;
value += (chunk, { stream: true });
(value); // Gradually output data
}
}
Through the above method, the JavaScript client can gradually process the asynchronous stream returned by the WebAPI, improving user experience and response speed.