Skip to content

Instantly share code, notes, and snippets.

@rpivo
Last active December 10, 2020 05:46
Show Gist options
  • Save rpivo/57f8a62c5e03707c93da2d1d35731d67 to your computer and use it in GitHub Desktop.
Save rpivo/57f8a62c5e03707c93da2d1d35731d67 to your computer and use it in GitHub Desktop.
Sync Methods in Node

Sync Methods in Node

It's very easy to get into callback hell in Node if the programmer needs to block the process and chooses not to use Node's sync methods (or its promise methods).

Since Node is made to deal with lots of streamed data, and since these streams have an unknown size and can take an unknown amount of time to complete, much of Node's functionality is built with callbacks to block parts of the process.

Even just simulating an arbitrary and minimal example of this, it's clear how obnoxiously complicated this can get.

function callFirst(cb) {
  const a = 1
  cb(a, callSecond)
}

function callSecond(val) {
  console.log(val)
}

callFirst(function (value, cb) {
  const increment = value + 1
  cb(increment)
})

Complexity aside, this pattern provides us with the ability to compose using functions. As is fairly common in Node, some of these functions will be named while others will be anonymous callbacks, which adds another layer of challenge.

Rather than having to rely on possibly nesting callbacks inside of other callbacks, most Node modules have a family of sync methods that can be used to block execution until they finish.

const data = fs.readFileSync('file.json')
console.log(JSON.parse(data)) // this won't happen until fs.readFileSync() is finished

This can also be done with promise methods that are exposed in most modules. Comparing sync methods with promise methods, there is not much difference other than just providing more options with syntax. Here's what the above would look like when importing from fs/promises:

(async function() {

  const data = await fs.readFile('file.json')
  console.log(JSON.parse(data)) // this won't happen until fs.readFileSync() is finished

})()

Using the fs/promises version requires the method to be called within an async context. It's a little more verbose, but also might be a little more clear as to what's going on, especially to others who may not be familiar with Node's sync methods.

It should be noted that both the sync and the fs/promise examples would benefit from being wrapped with try/catch blocks so that any exceptions don't bubble up and possibly kill the greater process.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment