Developer11
Developer11

Reputation: 781

Asynchronous function calls in Parallel

Following version is calling all functions synchronously,

I'm looking to find out how to call asynchronous functions in parallel and return all results and errors to the caller.

Request

let requestAsync (url: string) : Async<Result<string, Error>> =
    async {
        Console.WriteLine ("Simulating request " + url)
        try
            do! Async.Sleep(1000)
            return Ok (url + ": body...")
        with :? WebException as e ->
            return Error {code = 500; message = "Internal Server Error";}
    }

Test

[<TestMethod>]
member this.TestrequestAsync() =
    let urls = [|
        "http://www.example.com/1";
        "http://www.example.com/2";
        "http://www.example.com/3";
        "http://www.example.com/4";
        "http://www.example.com/5";
        "http://www.example.com/6";
        "http://www.example.com/7";
        "http://www.example.com/8";
        "http://www.example.com/9";
        "http://www.example.com/10";
    |]

    urls
    |> Array.map (fun url -> requestAsync url |> Async.RunSynchronously) // Async.Parallel some mismatch

    // Iterate results

Ideally to be able to match Ok and Error results while iterating through results

Edit based on the answer.

let result =
    urls
    |> Seq.map Entity.requestDetailAsync2
    |> Async.Parallel
    |> Async.RunSynchronously


result
|> Array.iter Console.WriteLine // match x with Ok and Error?

Attempt

result |> Array.iter (fun data -> match data with
                                      | Ok result -> Console.WriteLine(result)
                                      | Error error -> Console.WriteLine(error) )

Iteration using For in

for r in result do
    match r with
    | Ok re -> Console.WriteLine(re)
    | Error error -> Console.WriteLine(error)

Upvotes: 0

Views: 242

Answers (1)

Taylor Wood
Taylor Wood

Reputation: 16194

You can use Async.Parallel to run many async operations in parallel:

let results =
  urls
  |> Seq.map requestAsync   // seq<Async<'T>>
  |> Async.Parallel         // async<T' []>
  |> Async.RunSynchronously // T' []

Here's a very similar example on MSDN.

There may be an issue with your requestAsync function return type, or a missing type definition in your example. Here's what I used to verify the solution:

type RequestError = {
  code : int
  message : string
}

let requestAsync (url: string) =
    async {
        Console.WriteLine ("Simulating request " + url)
        try
            do! Async.Sleep(1000)
            return Ok (url + ": body...")
        with :? WebException as e ->
            return Error {code = 500; message = "Internal Server Error";}
    }

Upvotes: 2

Related Questions