One More Thin (Nim)…

Now that we have seen how Go and Python would do it, let's take a look at the implementation in Nim. This one is special because Nim is arguably a language that is a blend of Python and Go - it has very Python-like syntax, does type inference and cross-platform compilation of executable binaries like Go (maybe less streamlined for now). And it supports both async/await as well as "spawn" (coroutines) syntaxes.

As a reminder, in this example we are:

  1. Looking up a list of authors for the Microservices Architecture book, using Google Books API

  2. Looking up, in parallel, the number of books each author has published. This means issuing several concurrent API calls to Google books API, all at the same time.

  3. Waiting until all parallel lookups from #2 finish, since they can take different length of time, and when all of them are finished - printing out the results in a nicely-formatted way.

Chain Parallel with Sequential (Async/Await)

import httpclient, json, strformat, asyncdispatch, uri

const base_url = "https://www.googleapis.com/books/v1/volumes?q="

type
  Author* = object
   name*, uri*, count*: string

proc fetch(uri: string): Future[string] =
  echo fmt"Fetching: {uri}"
  var client = newAsyncHttpClient()
  result = client.getContent(uri) 

proc getAuthorsResults(authors: JsonNode) {.async.} =
  var authorsSeq = newSeq[Author](0) # empty at creation
  var lookups = newSeq[Future[string]](0)

  for authorJSON in authors:
    let author = authorJSON.getStr()
    let author_url = fmt"{base_url}inauthor:{encodeUrl(author)}"
    authorsSeq.add(Author(name: author, uri: author_url))
    lookups.add(fetch(author_url))

  var allResults =  await all(lookups)
  var c = 0
  for res in allResults:
    var rj = parseJson(res)
    var count = rj["totalItems"]
    echo fmt" {authorsSeq[c].name} - {count}"
    c.inc()


proc main() {.async.} =

  const msa_isbn = "1491956224"
  let   msa_url = fmt"{base_url}isbn:{msa_isbn}" # "Microservice Architecture"
  let response = await fetch(msa_url)

  let rj = parseJson(response)
  let authors = rj["items"][0]["volumeInfo"]["authors"]

  await getAuthorsResults(authors)


waitFor main()

# compile with:
# nim compile -d:ssl http.nim

Side note: full source code of this example can be found at: https://github.com/inadarei/nim-async

Last updated

Was this helpful?