Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Ignoring Operation Result when using F# async Computation Expression

0.00/5 (No votes)
6 Mar 2019 1  
Simple pitfall where C# developers trying out F# might fail when writing async code

Using the Code

Consider this simple code downloading page contents using Puppeteer-sharp.

let renderHtml = async {
    BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision) |> Async.AwaitTask |> ignore
    let options = LaunchOptions()
    options.Headless <- true
    let! browser = Puppeteer.LaunchAsync(options) |> Async.AwaitTask
    let! page = browser.NewPageAsync() |> Async.AwaitTask
    page.GoToAsync("https://i.ua") |> Async.AwaitTask |> ignore    
    return! page.GetContentAsync() |> Async.AwaitTask    
}

Since we actually don't care about download browser result, we naturally would expect that our line...

BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision) |> Async.AwaitTask |> ignore

...would be equivalent to this C# code:

await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);

However, when we execute the following method, we get Aggregate<wbr />Exception which in turn contains the following inner exception: "Chromium revision is not downloaded. Run BrowserFetcher.DownloadAsync or download Chromium manually". Seems like we've called...

let! browser = Puppeteer.LaunchAsync(options) |> Async.AwaitTask

...without waiting for BrowserFetcher result.

And indeed, in order to await async call, we have to use let! construct. The code below works as expected:

let renderHtml = async {
    let! _ = BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision) |> Async.AwaitTask
    let options = LaunchOptions()
    options.Headless <- true
    let! browser = Puppeteer.LaunchAsync(options) |> Async.AwaitTask
    let! page = browser.NewPageAsync() |> Async.AwaitTask
    let! _ = page.GoToAsync("https://i.ua") |> Async.AwaitTask    
    return! page.GetContentAsync() |> Async.AwaitTask    
}

Note how we use underscore to show that the variable value is ignored.

History

  • 6th March, 2019: Initial version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here