npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

with-defer

v1.0.0

Published

Run a function with an injected go-like defer helper

Downloads

295

Readme

with-defer

Because once you've tasted go's defer, you can't get enough.

This library provides tools to help you clean up resources in a simple and intuitive way. As you create more than one resource that needs to be disposed in a single, complex flow, you find yourself fighting with deeply-nested try / finally blocks and a sense of dread. "What happened to the flattened logic that I was promised with async / await?", you might ask. Fear not, we're here to help.

Using runWithDefer will allow you to colocate your instructions to free resources with their creation. Some real-world use-cases:

  • In tests, instead of having shared let variables instantiated in .before handlers and cleaned up in .after handlers, wrap your test logic in runWithDefer and get better typing and cleaner logic.
  • In complex CLI workflows or build tool logic, this can help dispose of handles that might otherwise keep the event loop open, preventing your app from cleanly exiting.
  • Manage the closing of your server and database connections.
  • ... we'd love to hear what else you can dream up.

Installation

npm install with-defer

Usage

Below is a fictitious example that opens a file handle for reading, and writes the contents of that file to another file handle opened for writing. Notice that the instructions to close the file handles are adjacent to the code that opens them. This makes it easy to understand the intent of the code.

Deferred clean-up functions will be run in FIFO order. This means the last registered clean-up function will run first. If a clean-up function returns a Promise, it will be awaited. Any rejections or thrown exceptions in clean-up functions will NOT prevent others from running. If any clean-up functions throw, these errors will be accumulated and the whole runWithDefer function will return a rejected Promise whose value is an AggregateError of the thrown exceptions.

Note: Yes, I know that there are 'better' ways to achieve the example below in Node.js. The point isn't so much writing one file's contents to another but how these file handles are cleaned up.

import * as Fs from 'fs';
import { runWithDefer } from 'with-defer';

async function main() {
  await runWithDefer(async (defer) => {
    // Open a file hande and make sure we close it.
    const handle1 = await Fs.promises.open('path/to/file', 'r+');
    defer(() => handle1.close());

    const content = await handle1.readFile('utf8');

    // We open a 2nd handle here and register its close function. Notice we don't have to deal
    // with crazy nesting of try / catch blocks and can co-locate clean-up with obtaining the
    // resource.
    const handle2 = await Fs.promises.open('path/to/file2', 'w+');
    defer(() => handle2.close());

    await handle2.writeFile(content);
  });
}

Docs

Read the API Documentation online.