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

nonsynchronous

v1.2.0

Published

async/await callback fusioning utilities

Downloads

5,434

Readme

nonsynchronous

async/await callback fusioning utilities

Functions

Promisify

Implementation:

const { promisify } = require('util')

The same promisify as provided in Node core.

Example:

const { promisify } = require('nonsynchronous')
const fs = require('fs')
const stat = promisify(fs.stat)
async function run () {
  console.log(await stat('.'))
}
run()

Once

Implementation:

const once = require('events.once')

The same once as provided in Node core (also polyfilled for earlier Node 10 versions).

Example:

const { once } = require('nonsynchronous')
const http = require('http')
async function run () {
  const server = http.createServer()
  server.listen()
  await once(server, 'listening')
  console.log(server.address())
}
run()

When

Useful for when you want to explicitly use a callback based API within an async function. The function returned from when must be called after awaiting the done method on that function other wise an error called before awaiting done() will be thrown.

Implementation:

const when = () => {
  var done = () => { throw Error('called before awaiting done()') }
  const fn = () => done()
  fn.done = promisify((cb) => { done = cb })
  return fn
}

Example:

const { when } = require('nonsynchronous')
async function run () {
  const until = when()
  setTimeout(() => {
    until()
  }, 1000)
  await until.done()
  console.log('timeout complete')
}
run()

Whenify

Useful for using a callback based API within an async function without any modifications required within the callback itself.

Must be used with a callback last API (for callback first, just use when manually).

Used in conjunction with the done symbol and optionally the count symbol. The asyncOps option is explored in the count symbol documentation.

Implementation:

const whenify = (fn, { asyncOps } = { asyncOps: 1 }) => {
  const until = when()
  const max = asyncOps - 1
  const result = (...args) => {
    const cb = args.pop()
    return fn(...args, (...args) => {
      cb(...args) // eslint-disable-line
      if (++result[count] > max) until()
    })
  }
  result[count] = 0
  Object.defineProperty(result, done, {
    get () { return until.done() }
  })
  return result
}

Example:

const { whenify, done } = require('nonsynchronous')
const fs = require('fs')
async function run () {
  const stat = whenify(fs.stat)
  stat('.', (err, stats) => {
    console.log(err, stats)
  })
  await stat[done]
}
run()

Whenify Method

Whenify an object method so that method[done] can be awaited (where done is the done symbol). This can be particularly useful when writing tests for an instance with callback based methods. The test be both self documenting and async compatible.

Implementation:

const whenifyMethod = (instance, method, opts) => {
  const result = whenify(instance[method].bind(instance), opts)
  instance[method] = result
  return instance
}

Example:

const { whenifyMethod, done } = require('nonsynchronous')
const fs = require('fs')
whenifyMethod(fs, 'stat')
async function run () {
  fs.stat('.', (err, stats) => {
    console.log(err, stats)
  })
  await fs.stat[done]
}
run()

Promisify Method

Convert a callback-based method on an instance into its promisifed equivalent. Can be passed multiple method names to easily promisify entire instances.

Implementation:

const _promisifyMethod = (instance, method) => {
  const result = promisify(instance[method])
  instance[method] = result
  return instance
}
const promisifyMethod = (instance, ...methods) => {
  methods.forEach(_promisifyMethod.bind(null, instance))
  return instance
}

Example:

const { promisifyMethod } = require('nonsynchronous')
const http = require('http')
async function run () {
  const server = http.createServer()
  promisifyMethod(server, 'listen')
  await server.listen()
  console.log(server.address())
}
run()

Promisify Of

Partially apply a promisify of a particular method on any given instance without mutating the instance. This is useful as an alternative to promisifyMethod if you don't want to overwrite instance keys and/or you have multiple different instances that you want to promisify the same method of.

Implementation:

const promisifyOf = (method) => {
  return (instance) => promisify((...args) => instance[method](...args))
}

Example:

const { promisifyOf } = require('nonsynchronous')
const http = require('http')
async function run () {
  const server = http.createServer()
  const listen = promisifyOf('listen')
  await listen(server)(2000) // listen on port 2000
  console.log(server.address())
}
run()

Immediate

Promisified setImmediate.

Implementation:

const immediate = promisify(setImmediate)

Example:

const { immediate } = require('nonsynchronous')
async function run () {
  console.log('this tick')
  await immediate()
  console.log('next tick')
}
run()

Timeout

Promisified setTimeout.

Implementation:

const timeout = promisify(setTimeout)

Example:

const { timeout } = require('nonsynchronous')
async function run () {
  await timeout(1000)
  console.log('timeout complete')
}
run()

Symbols

Done

The done symbol is used with whenify and whenifyMethod to access a promise on the function that has been whenified which can be awaited. The promise will complete once the callback for a whenified function has been called.

Count

The count symbol is used with whenify and whenifyMethod to access a the total amount of times a whenified functions callback was called. This is only useful when you set the asyncOps option to greater than 1.

const { whenify, done, count } = require('nonsynchronous')
const multiCallbackThing = whenify(
  require('multi-callback-thing'),
  {asyncOps: 3} // expecting three calls of the callback
)
async function run () {
  multiCallbackThing(() => {
    // how many times has this cb been called so far?
    // note: the count is zero indexed.
    console.log(`called ${multiCallbackThing[count] + 1} times`) 
  })
}
run()

Custom Promisify Args

The customPromisifyArgs symbol exposes a Node core symbol used to alter promisify behaviour for callbacks then have extra arguments.

const { promisify, customPromisifyArgs } = require('nonsynchronous')
const multiArgApi = (cb) => setImmediate(cb, null, 'circle', 'red')
multiArgApi[customPromisifyArgs] = ['shape', 'color']
const multiValApi = promisify(multiArgApi)

async function run () {
  const { shape, color } = await multiValApi()
  console.log(`shape: ${shape}\ncolor: ${color}`)
}
run()

Behaviors

Automatically includes and enable make-promisies-safe which causes Node to treat unhandled rejections as unhandled exceptions (e.g. throws and exits).

Tests & Coverage

npm test
Suites:   1 passed, 1 of 1 completed
Asserts:  24 passed, of 24
----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |      100 |      100 |                   |
 index.js |      100 |      100 |      100 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|

License

MIT