Another newbie question :-(

I'm still having difficulty in using async callback to update _future_ result 
with computed data (a time stamp in this case).

## Example code:
    
    
    # - 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 = 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
        client = newAsyncHttpClient()
        future = await client.getContent url
      
      result =  URLInfo(start: getTime(), url: url, content: future)
    
    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

## Sample Output:
    
    
    ➜  nim git:(master) ✗ nim r -d:ssl example.nim
    
    Correct durations are displayed:
    start  279 mSec  https://nim-lang.org yielded 42406 bytes in 50 uSec
    start  409 mSec  https://google.com yielded 14689 bytes in 19 uSec
    start  496 mSec  https://twitter.com yielded 93713 bytes in 1356 uSec
    start  531 mSec  https://facebook.com yielded 80313 bytes in 40 uSec
    start  654 mSec  https://youtube.com yielded 568834 bytes in 72 uSec
    start  713 mSec  https://amazon.com yielded 521418 bytes in 435 uSec
    start 1086 mSec  https://reddit.com yielded 795122 bytes in 733 uSec
    
    Wrong durations are displayed:
    start  279 mSec  https://nim-lang.org yielded 42406 bytes in 
-1646075063812694 uSec
    start  409 mSec  https://google.com yielded 14689 bytes in 
-1646075063942829 uSec
    start  496 mSec  https://twitter.com yielded 93713 bytes in 
-1646075064030065 uSec
    start  531 mSec  https://facebook.com yielded 80313 bytes in 
-1646075064064514 uSec
    start  654 mSec  https://youtube.com yielded 568834 bytes in 
-1646075064187285 uSec
    start  713 mSec  https://amazon.com yielded 521418 bytes in 
-1646075064246545 uSec
    start 1086 mSec  https://reddit.com yielded 795122 bytes in 
-1646075064619413 uSec
    Main Finshed: 7 sites
    
    
    Run

Reply via email to