Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

throw exception in async

Tags:

exception

f#

I have the following code:

member public this.GetData(uri: string) = async {
    let! res = Async.AwaitTask(httpClient.GetAsync uri)
    return res
}

When the property res.IsSuccessStatusCode is false I would like to throw an exception, how can I achieve this. The following code won't compile:

member public this.GetData(uri: string) = async {
    let! res = Async.AwaitTask(httpClient.GetAsync uri)
    match res.IsSuccessStatusCode with
    | true -> return res
    | false -> raise new Exception("")
}
like image 884
Knerd Avatar asked Jan 02 '14 22:01

Knerd


People also ask

What happens if an exception is thrown within an asynchronous method?

Async void methods have different error-handling semantics. When an exception is thrown out of an async Task or async Task method, that exception is captured and placed on the Task object.

How do I get async exception?

To catch an exception that an async task throws, place the await expression in a try block, and catch the exception in a catch block. Uncomment the throw new Exception line in the example to demonstrate exception handling. The task's IsFaulted property is set to True , the task's Exception.

Does await throw exception?

When you await a Task, the first exception is re-thrown, so you can catch the specific exception type (such as InvalidOperationException). However, when you synchronously block on a Task using Task. Wait or Task. Result, all of the exceptions are wrapped in an AggregateException and thrown.

How do you handle errors in async await react?

The last way to handle an error with async/await is called a higher order function. We have talked about this a couple of times now. A higher order function is a function that returns another function. The way it works is you go ahead and define all of your functions, just as if you were never to have any errors.


2 Answers

You certainly need to wrap new Exception(...) in brackets, but that is not sufficient in this case - both branches of the match statement need to return a value, so you also need to insert return:

async {
    let! res = Async.AwaitTask(httpClient.GetAsync uri)
    match res.IsSuccessStatusCode with
    | true -> return res
    | false -> return raise (new Exception(""))
}

This is actually easier to write using an if computation which can contain body that returns unit (and throws an exception if the operation did not succeed) - and so you do not need return in that case:

async {
    let! res = Async.AwaitTask(httpClient.GetAsync uri)
    if not res.IsSuccessStatusCode then
        raise (new Exception(""))
    return res 
}
like image 125
Tomas Petricek Avatar answered Oct 03 '22 18:10

Tomas Petricek


So the first part is that you need to wrap the new Exception() with brackets to make sure that F# interprets the code correctly.

raise (new Exception(""))

or you can use either of the pipe operators

raise <| new Exception("")
new Exception |> raise

or you can change the type and use failwith

failwith "some message"

Secondly, you need to return from both branches, so prefix raise with return

like image 36
John Palmer Avatar answered Oct 03 '22 18:10

John Palmer