Asynchronous Programming
34.1 std/asyncdispatch
Future[T], await, waitFor, asyncCheck (fire and forget, crashes on error), all, or, withTimeout, callSoon, runForever, poll.
Built on closure iterators and OS selectors (epoll/kqueue/IOCP).
import std/[asyncdispatch, httpclient]
proc fetch(url: string): Future[string] {.async.} =
let client = newAsyncHttpClient()
defer: client.close()
result = await client.getContent(url)
proc main() {.async.} =
let futs = @[fetch("https://nim-lang.org"), fetch("https://example.com")]
let pages = await all(futs)
for p in pages: echo p.len
await sleepAsync(500)
waitFor main()34.2 Async Networking
import std/[asyncnet, asyncdispatch]
proc handle(client: AsyncSocket) {.async.} =
while true:
let line = await client.recvLine()
if line.len == 0: break
await client.send("echo: " & line & "\r\n")
client.close()
proc serve() {.async.} =
let server = newAsyncSocket()
server.setSockOpt(OptReuseAddr, true)
server.bindAddr(Port(9000))
server.listen()
while true:
let client = await server.accept()
asyncCheck handle(client)
waitFor serve()34.3 Chronos
chronos (Status): an alternative async framework with stricter exception tracking (async: (raises: [...])), cancellation, better performance, and a rich ecosystem (chronos/apps/http, presto REST, websock, json_rpc).
asyncdispatch and chronos are not interoperable. Pick one per project.
34.4 Async Best Practices
Never block the event loop (CPU work goes to threads).
Handle errors on every future (try/await/except). Use timeouts.
Mixing threads and async: run separate dispatchers per thread and communicate via channels or AsyncEvent.