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

syncify

v1.2.1

Published

A radically simpler way to deal with asynchronous functions in javascript

Downloads

16

Readme

Syncify.js

Syncify is an innovative alternative to Async.js, Step and Node Fibers. It allows you to deal with "Callback Hell" in a very simple way.

It works just like Node Fibers in that it completely eliminates the need for callbacks. But, unlike Node Fibers, it also works on the browser!

Syncify Intro Video

Remove All The Callbacks

Example

Without Syncify

Assume that we have a very simple async function that issues an AJAX request to some remote REST API

ajax( url, callback )

This would be a typical composite function that calls the ajax() service several times:

function getFullName( id, cb ){
  ajax( "/user/" + id + "/name", function( err, name ){
    if ( err ){
      cb( err );
    } else {
      ajax( "/user/" + id + "/lastname", function( err, lastname ){
        if ( err ){
          cb( err )
        } else {
          cb( null, name + " " + lastname )
        }
      })
    }
  })
}

Uff. That's a lot of nested callbacks. Let's see if we can do better.

With Syncify

// 1. magically remove the callback from the ajax() service
ajax = syncify( ajax )

// 2. create a composite function. but this time without callbacks
function getFullName( id ){
	return ajax( "/user/" + id + "/name" ) + " " + ajax( "/user/" + id + "/lastname" )
}

// 3. add a callback to the resulting function so we can later use it
getFullName = syncify.revert( getFullName )

Both functions ( the one with syncify and the one without syncify ) are equivalent. You can call them like this:

getFullName( "aldo", function( err, res ){ console.log( res )})

Isn't that awesome?

Syncify allowed us to magically get rid of callbacks while creating a composite function. It is not just cleaner, but it also allows us to take advantage of the full power of Javascript.

You can use any function. For example:

function getNameUC( id ){
	return ajax("/user/" + id + "/name").toUpperCase()
}

You can even process a collection using Array.map()!

function getFriendNames( id ){
	return ajax("/user/" + id + "/friends").map( function( friend ){
		return ajax("/user/" + friend + "/name" ) + " " + ajax("/user/" + friend + "/lastname" )
  })
}

Or, same as above but using the function we had already defined

function getFriendNames( id ){
	return ajax("/user/" + id + "/friends").map( getFullName )
}

You can literally do anything. Syncify allows you to escape from Callback Hell so you can continue coding in regular Javascript.

Limitations

Well. To be honest. You cannot do just anything. You cannot use Syncify to deal with functions that mutate application state. That means you can exclusively use it with read-only functions.

While this sounds like a limitation, in practice it is not. Syncify is much better at composing queries ( functions that fetch data and draw the UI ) while Async.js is better at composing business logic. You can combine them.

To compensate for this limitation, Syncify has grown some cool tricks. For example, transparent concurrency.

Concurrency

You can make the above method much faster by using syncify.parallel:

function getFriendNames( id ){
  var friends = ajax("/user/" + id + "/friends")
  syncify.parallel(function(){
    // all requests issued within this block will be parallelized
    friends.map(function(){
      return ajax("/user/" + id + "/name" ) + " " + ajax("/user/" + id + "/lastname" )
    })
  })
}

The syncify.parallel() function is explained in this video.

Quickstart

Get the code

Using NPM

npm install syncify

Load Javascript on the browser

Syncify has no external dependencies. Just include it like you would any JS library:

<script src="http://aldonline.github.io/syncify/build/syncify-1.1.0.min.js"/>

If you prefer you can find the .js and .min.js builds in the /build directory.

API

syncify( asyncFunc: Function ): Function

Takes an async function and returns a syncified version

syncify.revert( syncifiedFunc: Function ): Function

Takes a syncified function ( or a function that contains nested syncified functions ) and returns an equivalent async function ( one that takes a callback ). This function is the counterpart/opposite of syncify().

syncify.parallel( block:Function )

See video ( top of the page )

syncify.sequence( block:Function )

See video ( top of the page )

Caveats

  • Functions must be idempotent
  • Their arguments must be JSON serializable
  • There are a few known bugs ( see issue #18 ). But other than that the code has been used in a dozen apps in production for over 4 months.