![](/img/trans.png)
[英]How to intercept an async method with IAsyncEnumerable<T> as return type in .netcore 3.0
[英]How to handle errors in method that has IAsyncEnumerable as return type
我有一個 API 端點:
[HttpGet("api/query")]
public async IAsyncEnumerable<dynamic> Query(string name)
{
await foreach(var item in _myService.CallSomethingReturningAsyncStream(name))
{
yield return item;
}
}
我希望能夠在 ArgumentException 的情況下返回類似“錯誤請求”的響應。
如果我嘗試使用 try-catch 塊,我會收到錯誤消息:
CS1626:無法在帶有 catch 子句的 try 塊主體中產生值
請注意,它是一個 API 端點方法,因此理想情況下錯誤處理應該在同一個方法中,而不需要制作額外的中間件。
你必須拆分方法。 提取進行異步處理的部分:
private async IAsyncEnumerable<dynamic> ProcessData(TypeOfYourData data)
{
await foreach(var item in data)
{
yield return item;
}
}
然后在 API 方法中執行:
[HttpGet("api/query")]
public IActionResult Query(string name)
{
TypeOfYourData data;
try {
data = _myService.CallSomethingReturningAsyncStream(name);
}
catch (...) {
// do what you need
return BadRequest();
}
return Ok(ProcessData(data));
}
或者實際上你可以將整個事情移動到單獨的方法中:
[HttpGet("api/query")]
public IActionResult Query(string name)
{
try {
return Ok(TheMethodYouMovedYourCurrentCodeTo);
}
catch (...) {
// do what you need
return BadRequest();
}
}
它當然只會捕獲在實際異步枚舉開始之前拋出的異常,但據我了解,這對您的用例來說很好。 在異步枚舉開始后返回錯誤的請求是不可能的,因為響應已經被發送到客戶端。
您可以安裝System.Interactive.Async package,然后執行以下操作:
[HttpGet("api/query")]
public IAsyncEnumerable<dynamic> Query(string name)
{
return AsyncEnumerableEx.Defer(() => _myService.CallSomethingReturningAsyncStream(name))
.Catch<dynamic, Exception>(ex =>
AsyncEnumerableEx.Return<dynamic>($"Bad request: {ex.Message}"));
}
Defer
算子的簽名:
// Returns an async-enumerable sequence that invokes the specified
// factory function whenever a new observer subscribes.
public static IAsyncEnumerable<TSource> Defer<TSource>(
Func<IAsyncEnumerable<TSource>> factory)
Catch
算子的簽名:
// Continues an async-enumerable sequence that is terminated by
// an exception of the specified type with the async-enumerable sequence
// produced by the handler.
public static IAsyncEnumerable<TSource> Catch<TSource, TException>(
this IAsyncEnumerable<TSource> source,
Func<TException, IAsyncEnumerable<TSource>> handler);
Return
操作員的簽名:
// Returns an async-enumerable sequence that contains a single element.
public static IAsyncEnumerable<TValue> Return<TValue>(TValue value)
Defer
可能看起來很膚淺,但在_myService.CallSomethingReturningAsyncStream
同步拋出的情況下需要它。 如果此方法作為async
迭代器實現,它永遠不會同步拋出異常,因此您可以省略Defer
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.