Hello everyone!
I am trying to make a bunch of http calls using the async http client. Code:
import httpClient, asyncdispatch
proc downloadAll(urls: seq[string]) {.async.} =
  var client = newAsyncHttpClient()
  for url in urls:
    var future = client.get(url)
    yield future
    if future.failed:
      echo "Problem!"
    else:
      echo "OK"
let urls = @[
  "http://127.0.0.1:5000/json",
  "http://127.0.0.1:5001/json",
  "http://127.0.0.1:5002/json",
]
waitFor downloadAll(urls)
 My expectation was that the yield would cause the event loop to schedule the get request and move on to the next iteration. However this code works sequentially. I know this is happening sequentially because localhost runs an app that sleeps for 5 seconds before serving the content and it takes 15s for this code to finish - I'd expect something close to 5s
I'd like to better understand why this happens. Does yield not do what I think it does inside a loop?
p.s. FWIW, I have another version based on previous threads on this forum that works that uses two procs to get the job done but I was wondering if there was a simpler way to go about it.
Thanks! Deepak
So I changed it a little:
proc downloadAll(urls: seq[string]) {.async.} =
  var client = newAsyncHttpClient()
  var futures = newSeq[Future[string]]()
  for url in urls:
    var future = client.getContent(url)
    futures.add(future)
  
  var results = await all(futures)
  echo("All Done")
let urls = @[
  "http://localhost:80/status/200",
  "http://localhost:80/status/500",
]
But now I get a runtime crash because the second request would lead to an exception. Is there a clean way to catch an error from an individual future?
If I change both urls to status/200, i.e.
let urls = @[
  "http://localhost:80/status/200",
  "http://localhost:80/status/200",
]
 I get a different problem:
Exception message: Connection was closed before full request has been made Exception type: [ProtocolError]
So looks like I also need a unique async httpclient instance per request. Is that right?
the problem that the client cannot be shared to other download
import httpClient, asyncdispatch
proc download(url: string): Future[string] {.async.} =
    await newHttpClient().getContent(url)
}
proc downloadAll(urls: seq[string]) {.async.} =
  var asyncresult = newseq[Future[string]](urls.len)
  for i, url in urls:
    asyncresult[i] = download url
  await all(asyncresult)
let urls = @[
  "http://127.0.0.1:5000/json",
  "http://127.0.0.1:5001/json",
  "http://127.0.0.1:5002/json",
]
waitFor downloadAll(urls)Thanks!
How/Where would you handle errors that arise during await all(asyncresult). For example an http 500 from the server which becomes an exception. Would proc download be responsible for handling it?