That seems to work!
# - How can I get access to the completion time (info.finish) when the
request
# has been fullfilled?
# - My guess is that in the callback *info* is being *passed by value* so
the timestamp
# (info.finish) isn't being updated ( and is returned as zero :-( )
import std/[algorithm, asyncdispatch, httpclient, strutils, times]
var startTime: Time
type URLinfo = ref object
start: Time
finish: Time
url: string
content: string
proc duration(info: URLinfo): Duration =
info.finish - info.start
proc startOffset(info: URLinfo) : Duration = # relative timestamp
info.start - startTime
proc `$`(info: URLinfo): string =
"start " & align($(info.startOffset.inMilliseconds), 4) & " mSec " &
info.url & " yielded " & $(info.content.len) &
" bytes in " & $(info.duration.inMicroseconds) & " uSec"
proc fetch(url: string): Future[URLinfo] {.async.} =
let
startTime = getTime()
client = newAsyncHttpClient()
result = URLInfo(start: startTime, url: url)
result.content = await client.getContent url
proc getURLs(urls: seq[string]) : Future[seq[URLinfo]] {.async.} =
var futures: seq[Future[URLinfo]]
startTime = getTime()
echo "\nCorrect durations are displayed:"
for url in urls:
var future = fetch url
future.addCallback(
proc(future: Future[URLinfo]) =
var info = future.read
info.finish = getTime() # Doesn't update original URLinfo :-(
echo $info
)
futures.add future
result = await all futures
echo "\nWrong durations are displayed:"
for entry in result.sortedByIt(it.startOffset): echo entry
proc main() {.async} =
var sites = @[
"https://amazon.com",
"https://facebook.com",
"https://google.com",
"https://nim-lang.org",
"https://reddit.com",
"https://twitter.com",
"https://youtube.com",
]
echo "Main Finshed: ", (await getURLs sites).len, " sites"
waitFor main()
Run