#sync with spawn import httpclient, json , times, threadpool
} let response = client.request("https://reqres.in/api/strategy", httpMethod = HttpPost, body = $body) echo response.status echo response.body echo("done " & $i)
sync() # it took me some time to understand that here was correct, i originally indented it on spawn level
let time = cpuTime() loop(10) #sync() #here also works. What is the difference? echo "Time taken: ",cpuTime() - time
import httpclient, asyncdispatch, json , times let time = cpuTime()
let response = await client.request("https://reqres.in/api/strategy", httpMethod = HttpPost, body = $body) echo response.status echo await response.body echo("done " & $i)
waitFor loop(10) echo "Time taken: ",cpuTime() - time
Hmm, I don't immediately see why the async version doesn't print.
I believe there's no real difference between putting sync() at the end of the proc or after you call it. It's a matter of preference/design.
By the way, it's better not to discard Future s, because async code has a different semantic for error handling. Any time you call an async proc, it will implicitly return a future, which is a "black box" that will eventually contain a completed result. If you discard the Future , you will miss the chance to check for errors. That means you could ignore an exception if one is thrown. So, instead of using discard to handle the future, use asyncCheck , like this:
echo "executing call number: " , i
asyncCheck callStrategy(i)
The asyncCheck procedure adds a callback to the "black box" that re-throws any exception that might have occurred while the async code was running. That way, you don't miss any errors.
Oh, and I'm wondering why you have an await here after the last echo :
let response = await client.request("https://reqres.in/api/strategy",
httpMethod = HttpPost,
body = $body)
echo response.status
echo await response.body
I haven't used the Async HTTP module, but I'm wondering if response.body is just a normal field that can't actually be await ed.I just had a look at the docs, and I'm going to suggest dropping that await after the echo (see above). Let us know if that works!
Cheers!
Hi @Kvothe Welcome to Nim.
In async problem, I think it's because the hit not actually executed yet but only registered on dispatcher.
Usually when using async, we run it forever with runForever or wait each invocation with waitFor (but this is not what you wanted).
Thanks for the reply. Unfortunately removing the await after the echo it refuses to compile.
if i keep the await and put asyncCheck it complies but does not print any response. Finally, if instead of asyncCheck i use waitFor it prints everything as expected, but does it in a synchronous way.
Here is what you need to do to replicate your spawn example:
# async version
import httpclient, asyncdispatch, json , times
let time = cpuTime()
proc callStrategy (i : int) {.async.} =
echo("request " & $i)
let client = newAsyncHttpClient()
client.headers = newHttpHeaders({ "Content-Type": "application/json" })
let body = %*{
"Pid":i
}
let response = await client.request("https://reqres.in/api/strategy",
httpMethod = HttpPost,
body = $body)
echo response.status
echo await response.body
echo("done " & $i)
proc loop (num: int) {.async.} =
echo "executing call number: " , num
var futures: seq[Future[void]] = @[]
for i in 1..num:
echo "executing call number: " , i
futures.add callStrategy(i)
await all(futures)
waitFor loop(10)
echo "Time taken: ",cpuTime() - time