You are viewing the preview version of this book
Click here for the full version.

The async disposer pattern

A recurring pattern is to run some initialization code to set up some resource or configuration, then use the thing, and finally do some cleanup. It can be a global property, such as freezing the time with timekeeper, starting a Chrome browser with Puppeteer, or creating a temp directory. In all these cases, you need to make sure the modifications/resources are properly disposed of, otherwise, they might spill out to other parts of the codebase.

For example, this code creates a temp directory in the system tmpdir then when it's not needed it deletes it. This can be useful when, for example, you want to use ffmpeg to extract some frames from a video and need a directory to tell the ffmpeg command to output the images to.

// create the temp directory
const dir = await fs.mkdtemp(
  await fs.realpath(os.tmpdir()) + path.sep
);
try {

  // use the temp directory

} finally {
  // remove the directory
  fs.rmdir(dir, {recursive: true});
}

A similar construct is console.time that needs a console.timeEnd to output the time it took for a segment of the code to run:

console.time("name");
try {
  // ...
} finally {
  console.timeEnd("name");
}

Or when you launch a browser, you want to make sure it's closed when it's not needed:

const browser = await puppeteer.launch({/* ... */});
try {
  // use browser
} finally {
  await browser.close();
}

All these cases share the try..finally structure. Without it, an error can jump over the cleanup logic, leaving the resource initialized (or the console timing still ticking):

const browser = await puppeteer.launch({/* ... */});

// if there is an error here the browser won't close!

await browser.close();

In other languages, such as Java, this is known as try-with-resources and it is built into the language. For example, the BufferedReader is closed after the block:

try (BufferedReader br =
  new BufferedReader(new FileReader(path))
) {
  return br.readLine();
}
There is more, but you've reached the end of this preview
Get a subscription to get access to the full book.