簡體   English   中英

如何處理以 IAsyncEnumerable 作為返回類型的方法中的錯誤

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM