0

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)

1 Answer 1

2

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";}
    }
Sign up to request clarification or add additional context in comments.

5 Comments

thanks, Can you please add the portion for iteration, see my edit please
so if I were to explain the answer, you created a sequence of requestAsync calls and called all of them in parallel Async.Parallel and waited for them to finish Async.RunSynchronously
please see my attempt, do you agree with my attempt or is there a beautiful elegant solution?
@Developer11 your code that iteratively prints the results looks fine to me, though there are other ways to factor it e.g. you might find for .. in .. do reads better.
please check for in edit, is that how what you meant?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.