I am trying to write non-blocking code in F#. I need to download a webpage, but sometime that webpage doesn't exist and an exception is thrown (404 Not Found) by AsyncDownloadString. I tried the code below but it doesn't compile.
How could I handle exception from AsyncDownloadString?
let downloadPage(url: System.Uri) = async {
try
use webClient = new System.Net.WebClient()
return! webClient.AsyncDownloadString(url)
with error -> "Error"
}
How am I suppose to handle exception here? If an error is thrown, I simply want to return an empty string or a string with a message in it.
1 Answer 1
Just add the return keyword when you return your error string:
let downloadPage(url: System.Uri) = async {
try
use webClient = new System.Net.WebClient()
return! webClient.AsyncDownloadString(url)
with error -> return "Error"
}
IMO a better approach would be to use Async.Catch instead of returning an error string:
let downloadPageImpl (url: System.Uri) = async {
use webClient = new System.Net.WebClient()
return! webClient.AsyncDownloadString(url)
}
let downloadPage url =
Async.Catch (downloadPageImpl url)
3 Comments
Async.Catch is better because: (1) it preserves information about the error...there are other reasons an exception might be thrown besides a 404, and having the exception instead of "Error" makes it easier to diagnose the problem; (2) using Choice<_,_> allows you to use the type system to enforce the processing paths for both the results and the errors.Async.Catch can "leak" an exception (for example when an exception is thrown before the async is created - see: gist.github.com/jwosty/c6cb8ae1111ccc5caeb0f6db591d879e). Using a try-with block catches that exception.