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

release-zalgo

v1.0.0

Published

Helps you write code with promise-like chains that can run both synchronously and asynchronously

Downloads

13,372,208

Readme

release-zalgo

Helps you write code with promise-like chains that can run both synchronously and asynchronously.

Installation

$ npm install --save release-zalgo

Usage

If you use this module, you'll release Ẕ̶̨̫̹̌͊͌͑͊̕͢͟a̡̜̦̝͓͇͗̉̆̂͋̏͗̍ͅl̡̛̝͍̅͆̎̊̇̕͜͢ģ̧̧͍͓̜̲͖̹̂͋̆̃̑͗̋͌̊̏ͅǫ̷̧͓̣͚̞̣̋̂̑̊̂̀̿̀̚͟͠ͅ. You mustn't do that.

Before you proceed, please read this great post by Isaac Schlueter on Designing APIs for Asynchrony.

The first rule of using this package is to keep your external API consistent.

The second rule is to accept the burden of controlling Ẕ̶̨̫̹̌͊͌͑͊̕͢͟a̡̜̦̝͓͇͗̉̆̂͋̏͗̍ͅl̡̛̝͍̅͆̎̊̇̕͜͢ģ̧̧͍͓̜̲͖̹̂͋̆̃̑͗̋͌̊̏ͅǫ̷̧͓̣͚̞̣̋̂̑̊̂̀̿̀̚͟͠ͅ by ensuring he does not escape your API boundary.

With that out of the way… this package lets you write code that can run both synchronously and asynchronously. This is useful if you have fairly complex logic for which you don't want to write multiple implementations. See package-hash for instance.

This is best shown by example. Let's say you have a hashFile() function:

const crypto = require('crypto')
const fs = require('fs')

function hashFile (file) {
  return new Promise((resolve, reject) => {
    fs.readFile(file, (err, buffer) => err ? reject(err) : resolve(buffer))
  })
    .then(buffer => {
      const hash = crypto.createHash('sha1')
      hash.update(buffer)
      return hash.digest('hex')
    })
}

A synchronous version could be implemented like this:

function hashFileSync (file) {
  const buffer = fs.readFileSync(file)
  const hash = crypto.createHash('sha1')
  hash.update(buffer)
  return hash.digest('hex')
}

Here's the version that uses release-zalgo:

const crypto = require('crypto')
const fs = require('fs')

const releaseZalgo = require('release-zalgo')

const readFile = {
  async (file) {
    return new Promise((resolve, reject) => {
      fs.readFile(file, (err, buffer) => err ? reject(err) : resolve(buffer))
    })
  },

  sync (file) {
    return fs.readFileSync(file)
  }
}

function run (zalgo, file) {
  return zalgo.run(readFile, file)
    .then(buffer => {
      const hash = crypto.createHash('sha1')
      hash.update(buffer)
      return hash.digest('hex')
    })
}

function hashFile (file) {
  return run(releaseZalgo.async(), file)
}

function hashFileSync (file) {
  const result = run(releaseZalgo.sync(), file)
  return releaseZalgo.unwrapSync(result)
}

Note how close the run() implementation is to the original hashFile().

Just don't do this:

function badExample (zalgo, file) {
  let buffer
  zalgo.run(readFile, file)
    .then(result => { buffer = result })

  const hash = crypto.createHash('sha1')
  hash.update(buffer)
  return hash.digest('hex')
}

This won't work asynchronously. Just pretend you're working with promises and you'll be OK.

API

First require the package:

const releaseZalgo = require('release-zalgo')

releaseZalgo.sync()

Returns a zalgo object that runs code synchronously:

const zalgo = releaseZalgo.sync()

releaseZalgo.async()

Returns a zalgo object that runs code asynchronously:

const zalgo = releaseZalgo.async()

releaseZalgo.unwrapSync(thenable)

Synchronously unwraps a thenable, which is returned when running synchronously. Returns the thenables fulfilment value, or throws its rejection reason. Throws if the thenable is asynchronous.

zalgo.run(executors, ...args)

When running synchronously, executors.sync() is called. When running asynchronously executors.async() is used. The executer is invoked immediately and passed the remaining arguments.

For asynchronous execution a Promise is returned. It is fulfilled with executors.async()'s return value, or rejected if executors.async() throws.

For synchronous execution a thenable is returned. It has the same methods as Promise except that callbacks are invoked immediately. The thenable is fulfilled with executors.sync()'s return value, or rejected if executors.sync() throws.

zalgo.all(arr)

When running synchronously, returns a new thenable which is fulfilled with an array, after unwrapping all items in arr.

When running asynchronously, delegates to Promise.all(arr).

zalgo.returns(value)

When running synchronously, returns a new thenable which is fulfilled with value.

When running asynchronously, delegates to Promise.resolve(value).

zalgo.throws(reason)

When running synchronously, returns a new thenable which is rejected with reason.

When running asynchronously, delegates to Promise.reject(reason).

Thenables

Thenables are returned when running sychronously. They're much like Promises, in that they have then() and catch() methods. You can pass callbacks and they'll be invoked with the fulfilment value or rejection reason. Callbacks can return other thenables or throw exceptions.

Note that then() and catch() must be called on the thenable, e.g. thenable.then(), not (thenable.then)().

Thenables should not be exposed outside of your API. Use releaseZalgo.unwrapSync() to unwrap them.