简体   繁体   English

如何处理以 IAsyncEnumerable 作为返回类型的方法中的错误

[英]How to handle errors in method that has IAsyncEnumerable as return type

I have an API endpoint:我有一个 API 端点:

[HttpGet("api/query")]
public async IAsyncEnumerable<dynamic> Query(string name)
{    
   await foreach(var item in _myService.CallSomethingReturningAsyncStream(name))
   {
       yield return item;
   }
}

I would like to be able to in case of an ArgumentException return something like "Bad request" response.我希望能够在 ArgumentException 的情况下返回类似“错误请求”的响应。

If I try using try-catch block, I get error :如果我尝试使用 try-catch 块,我会收到错误消息:

CS1626: Cannot yield a value in the body of a try block with a catch clause CS1626:无法在带有 catch 子句的 try 块主体中产生值

Please note that it is an API endpoint method, so error handling should ideally be in the same method, without need for making additional middlewares.请注意,它是一个 API 端点方法,因此理想情况下错误处理应该在同一个方法中,而不需要制作额外的中间件。

You have to split method.你必须拆分方法。 Extract part which does async processing:提取进行异步处理的部分:

private async IAsyncEnumerable<dynamic> ProcessData(TypeOfYourData data)
{    
   await foreach(var item in data)
   {
       yield return item;
   }
}

And then in API method do:然后在 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));
}

Or actually you can just move the whole thing into separate method:或者实际上你可以将整个事情移动到单独的方法中:

[HttpGet("api/query")]
public IActionResult Query(string name)
{           
   try {
       return Ok(TheMethodYouMovedYourCurrentCodeTo);
   }
   catch (...) {
        // do what you need
        return BadRequest();
   }
}

It will of course only catch exceptions thrown before actual async enumeration starts, but that's fine for your use case as I understand.它当然只会捕获在实际异步枚举开始之前抛出的异常,但据我了解,这对您的用例来说很好。 Returning bad request after async enumeration has started is not possible, because response is already being sent to client.在异步枚举开始后返回错误的请求是不可能的,因为响应已经被发送到客户端。

You could install the System.Interactive.Async package, and do this:您可以安装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}"));
}

The signature of the Defer operator: 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)

The signature of the Catch operator: 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);

The signature of the Return operator: Return操作员的签名:

// Returns an async-enumerable sequence that contains a single element.
public static IAsyncEnumerable<TValue> Return<TValue>(TValue value)

The Defer might seem superficial, but it is needed for the case that the _myService.CallSomethingReturningAsyncStream throws synchronously. Defer可能看起来很肤浅,但在_myService.CallSomethingReturningAsyncStream同步抛出的情况下需要它。 In case this method is implemented as an async iterator , it will never throw synchronously, so you could omit the Defer .如果此方法作为async迭代器实现,它永远不会同步抛出异常,因此您可以省略Defer

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用 IAsyncEnumerable 拦截异步方法<t>作为 .netcore 3.0 中的返回类型</t> - How to intercept an async method with IAsyncEnumerable<T> as return type in .netcore 3.0 如何使用 IAsyncEnumerable 对方法进行单元测试<dynamic>返回类型</dynamic> - How to unit test method with IAsyncEnumerable<dynamic> return type 从异步方法返回 IAsyncEnumerable - Return IAsyncEnumerable from an async method 为什么我不允许在返回 IAsyncEnumerable 的方法中返回 IAsyncEnumerable - Why am I not allowed to return an IAsyncEnumerable in a method returning an IAsyncEnumerable 如何使用 SqlDataReader 返回和使用 IAsyncEnumerable - How to Return and Consume an IAsyncEnumerable with SqlDataReader 从已经具有返回类型的方法中获取错误 - Getting errors from a method that already has a return type 是否可以在异步方法中返回指向 IAsyncEnumerable 的指针? - Is it possible to return a pointer to an IAsyncEnumerable in an async method? 如何与异步 foreach 和 IAsyncEnumerable 一起返回 ActionResult - How to return ActionResult along with async foreach and IAsyncEnumerable 如何在具有返回类型的方法中调用异步方法? - How to call async method inside a method which has return type? 扩展具有返回类型的方法 - Extending a method that has a return type
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM