Hello, I'm starting an application (that I hope to become a mail client using the JMAP protocol), and I'm trying the fidget GUI toolkit. I have a problem with it, however, I can't make async futures work.
I can't make use of built-in fidget HTTP helper, as I need to make POST requests instead of GET requests, so I instantiated an AsyncHttpClient object. However, when I make the async call, I never get in the future callback, or past the await in the async proc.
The async proc looks like this ( jmap/transport.nim):
proc request*(t: Transport, req: sink Request): Future[Response] {.async.} =
var gen: Generator
for meth in items(req.methodCalls):
if meth.id != "": gen.incl(meth.id)
for meth in items(req.methodCalls):
if meth.id == "": meth.id = gen.id()
let body = req.toJson
echo &"request body = {body}"
let fut = t.http.post(t.url, body = body)
fut.addCallback do():
echo "callback ok"
let resp = await fut
echo "got response headers"
let json = await(resp.body)
echo &"got response body = {json}"
var response: Response = json.fromJson(Response)
return response
and I never get past the "request body =" message.
The future is called in actions/login.nim, it's another async procedure with an await. The async procedure is called from a onClick fidget callback in ui/login.nim:
group "button":
box 140, 110, 100, 30
button("Login")
onClick:
asyncCheck refreshAfter(login(v.config, v.account))
v.login_progress = true
with the refreshAfter procedure, that is supposed to hook up the future with fidget as below (in ui/common.nim):
proc refreshCallback() =
echo "refreshCallback"
fidget.refresh()
proc refreshAfter*[T](future: Future[T]): Future[T] =
future.addCallback(refreshCallback)
return future
I'm not sure what I'm doing wrong here. I suppose the future is somehow not registered with the event loop, but I don't know how to do that. I also noticed that I could get past the first callback if I replaced all the async with waitFor which I did by mistake at first.
If you want to test the code, you can trigget this by running the app and trying to login with any e-mail @mildred.fr or @jmap.io.
Thank you
That simple, it makes sense. I thought fidget did that already since it uses internally futures for its own HTTP get requests.
Reading the code more closely it seems you're right:
while base.running:
updateLoop()
asyncPoll()
https://github.com/treeform/fidget/blob/973ce77faff418244de95154a7ed8761d8726374/src/fidget/openglbackend.nim#L370-L378
proc asyncPoll() =
when not defined(emscripten) and not defined(fidgetNoAsync):
var haveCalls = false
for call in httpCalls.values:
if call.status == Loading:
haveCalls = true
break
if haveCalls:
poll()
It calls poll() only if it have registered HTTP calls.
Thank you