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

callstep

v1.0.0

Published

async control flow library using continuables

Downloads

5

Readme

callstep 🚶

Promise-like async control flow library using plain functions

npm install --save callstep

table of contents

concepts

Callback

Callback<Error, Value>(err : Error, value : Value) => void

a callback is a function that is called (usually asynchronously) with an error as the first and a value as the second argument.

this was the most common asynchronous pattern in Node.js code, until Promises.

guess who's back meow, callbacks! 🐈

function callback (err, value) {}

Continuable

Continuable<Error, Value>(callback : Callback<Error, Value>) => void

a continuable is a function with one argument: a callback.

a continuable is a future value that can be asynchronously resolved later, like a Promise!

function continuable (callback) {
  // do something, then call...
  callback(err, value)
}

for example:

function readConfig (callback) {
  fs.readFile('./config.json', callback)
}

Callstep

Callstep<Error, Input, Output>(value : Input) => Continuable<Error, Output>

a callstep is a function that receives an input value and returns a continuable for an output value.

function callstep (input) {
  function continuable (callback) {
    callback(err, output)
  }
}

for example:

const readConfig = readFile('./config.json')

function readFile (path) {
  return function continuable (callback) {
    fs.readFile('./config.json', callback)
  }
}

api

step = require('callstep')

step.of(value) => continuable

step.of(value : Value) => Continuable<null, Value>`

given a value, returns a continuable for the value.

source:

function of (value) {
  return callback => callback(null, value)
}

step.error(err) => continuable

step.error(err : Error) => Continuable<Error, null>`

given an error, returns a continuable for the error.

source:

function error (err) {
  return callback => callback(err)
}

step.to(asyncFn) => (...values) => continuable

convert an async function (for example fs.readFile) to a function that returns a continuable

for example:

var readFile = step.to(fs.readFile)

var readConfig = readFile('./config.json', 'utf8')

readConfig((err, text) => {
  console.log(text)
})

source:

function to (asyncFn) {
  return function (...args) {
    return function continuable (callback) {
      return asyncFn(...args, callback)
    }
  }
}

step.noop() => continuable

step.noop() => Continuable<null, null>

returns a continuable for nothing.

source:

function noop () {
  return callback => callback(null, null)
}

step.sync(syncFn) => continuable

step.sync(syncFn : () => { return value : Value | throw err : Error }) => Continuable<Error, Value>

given a synchronous function that returns a value or throws an error,

returns a continuable for the value or any caught error.

for example:

const parseJson = json => step.sync(() => JSON.parse(json))

source:

function sync (fn) {
  return callback => {
    try {
      var result = fn()
    } catch (err) {
      return callback(err)
    }
    callback(null, result)
  }
}

step.series([...continuables]) => continuable

step.series(continuables : [Continuable]) => Continuable<Error, [Result]>

given an array of continuables, returns a continuable to invoke them in order.

the callback will receive an error if one errors, or an array of results if all succeed.

uses run-series

for example:

const runSteps = step.series([stepOne, stepTwo])

step.parallel([...continuables]) => continuable

step.parallel(continuables : [Continuable]) => Continuable<Error, [Result]>

given an array of continuables, returns a continuable to invoke them in parallel.

the callback will receive an error if any error, or an array of results if all succeed.

uses run-parallel

for example:

const fetchAnimals = step.parallel([fetchCats, fetchDogs, fetchBirds])

step.waterfall([continuable, ...callsteps]) => continuable

step.waterfall([continuable, ...callsteps]) => Continuable<Error, FinalResult>

given an array of continuables return a continuable that invokes them in order, or until one errors.

uses run-waterfall

for example:

const readFile = step.to(fs.readFile)
const parseJson = json => step.sync(() => JSON.parse(json))

const readConfig = step.waterfall([
  readFile('./config.json'),
  parseJson
])

step.iff(predicate, ifTrue, ifFalse?) => callstep

step.iff(predicate : (value : Value) => Boolean, ifTrue : Callstep<Error, Value>, ifFalse : CallStep<Error, Value>) => CallStep<Error, Value>

given a predicate function that returns true or false, a ifTrue callstep if predicate is true, and an optional ifFalse callstep if predicate is false (otherwise defaults to step.of).

returns a callstep that will conditionally delegate to either ifTrue or ifFalse depending on the result of predicate.

const isString = value => typeof(value) === 'string'
const parseJson = json => step.sync(() => JSON.parse(json))

const toJson = step.iff(isString, parseJson)

step.map(source, lambda) => continuable

given a source continuable and a lambda synchronous transformation function, returns a new continuable.

the new continuable is the result of the first continuable transformed by your synchronous mapping function.

step.map<Error, Input, Output>(source : Continuable<Error, Input>, lambda : (input : Input) => { return output : Output | throw err : Error }) => Continuable<Error, Output>

for example:

const readConfig = map(
  readFile('./config.json', 'utf8'),
  JSON.parse
)

readConfig((err, config) => {
  console.log(config)
})

step.mapAsync(source, callstep) => continuable

given a source continuable and a callstep asynchronous transformation function, returns a new continuable.

the new continuable is the result of the first continuable transformed by your asynchronous mapping function.

step.map<Error, Input, Output>(source : Continuable<Error, Input>, callstep : Callstep<Error, Input, Output>) => Continuable<Error, Output>

for example:

const writeConfig = mapAsync(
  readFile('./config.json', 'utf8'),
  JSON.parse
)

readConfig((err, config) => {
  console.log(config)
})

step.swallowError(continuable) => continuable

step.swallowError(continuable : Continuable<Error, Value>) => Continuable<null, Value>

given a continuable, returns a new continuable that ignores any errors passed to the callback.

const parseJson = json => step.sync(() => JSON.parse(json))

const tryParseJson = value => step.swallowError(parseJson(value))

step.tap(fn) => callstep

step.tap(fn : (value : Value) => void) => CallStep<Error, Value>

given a tap function that receives a value, returns a callstep which runs the tap function before returning a continuable for the value.

helpful for debugging callsteps.

for example:

const readFile = step.to(fs.readFile)
const parseJson = json => step.sync(() => JSON.parse(json))

const readConfig = step.waterfall([
  readFile('./config.json'),
  step.tap(value => console.log('value', value)),
  parseJson
])

thanks

license

The Apache License

Copyright © 2018 Michael Williams

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.