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 🙏

© 2026 – Pkg Stats / Ryan Hefner

shakle

v1.0.5

Published

A vanilla JS promise library to help with your asynchronous todo list!

Readme

Shakle

npm travis

A vanilla JS promise library to help with your asynchronous todo list!

ShakleLogo2


Shakle is a lightweight module that gives you access to a Promise class and some useful methods. All in pure Javascript!

DISCLAIMER: The promise class provided almost meets all the specs outlined in Promise/A+ spec. While this module is completely functional, it is primarily for educational purposes.

You have access to:

Usage


Get started by first downloading Shakle from npm

npm install shakle --save

Then require it in your project

var Shakle = require('shakle');

Now you can start chaining together your TODOs!

(get it? 'chain together'?? shakle??? ...shut up, it's clever.)

var resolveValue = function (value) {
    return new Shakle(function(resolve) {
        resolve(value);
    });
}

The invocation of resolveValue returns a promise with a .then() method which takes a callback to invoke on the value that resolves from the Promise

resolveValue(2)
    .then(function(value) {
        console.log(value)
    })
    
//logs 2 to the console

What makes Promises so special is that they invoke the callback passed to .then() on the resolved value WHENEVER IT HAPPENS TO COME BACK!

An example is in order:

var resolveValueInOneSecond = function (value) {
    return new Shakle(function(resolve) {
        setTimeout(function() {
             resolve(value);
        }, 1000);
    });
}

resolveValueInOneSecond(2)
    .then(function(value) {
        console.log(value)
    })
    
//logs 2 to the console ONE SECOND LATER!

This is a great way to deal with async functions in a clean, easy to read, non-blocking way

Another powerful feature of promises is that the .then() method always returns another promise.

This means you can keep chaining together functions indefinitely! WOW!

Check it out:

var doubler = function(value) {
    return value * 2
}

resolveValueInOneSecond(2)
    .then(doubler)
    .then(doubler)
    .then(doubler)
    .then(doubler)
    .then(function(value) {
        console.log(value)
    })
    
//logs 32 to the console one second later

As you might have noticed, the return value of a callback is passed down to the the input of the callback in the .then() chained below it

But what if the callback returns a Promise rather than a resolved value?

Well, this promise class is smart enough to recognize this and try to resolve it with the callback in the .then() chained below.

Check it out:

resolveValueInOneSecond(2)
    .then(doubler)
    .then(resolveValueInOneSecond)
    .then(doubler)
    .then(resolveValueInOneSecond)
    .then(doubler)
    .then(function(value) {
        console.log(value)
    })
    
//logs 16 to the console THREE SECONDS LATER!

Built-in Methods


.promisify()

.promisify() takes in a function that would take in a callback and returns a function that takes no callback and instead returns a promise

For example:

var fs = require('fs');

var shakledReadFile = Shakle.promisify(fs.readFile);

The returned function still takes in the non callback parameters like so:

shakledReadFile('alphabet.txt', 'utf-8')
    .then(function(data) {
        console.log(data)
    })
    
// logs the contents of alphabet.txt whenever the file system is finished being read

Then you could chain together various synchronous and asynchronous functions to process the file contents further:

shakledReadFile('alphabet.txt', 'utf-8')
    .then(parse)
    .then(sort)
    .then(send)
    .then(doSomethingElse)

Keep in mind that the callback that .promisify() abstracts away needs to be in the format below:

function(err, result) {
    // ...
}

Error Handling


One other method on a promise object along with .then() is .catch()

.catch() accepts a callback that does something with errors that are thrown in the callback chain

Let's look at how .catch() works:

var shakledReadFile = function(input) {
    return new Shakle(function(resolve, reject) {
        fs.readFile(input, 'utf-8', function(err, result) {
            if (err) {
                reject(err);
            } else {
                resolve(result);
            }
        })
    })
}


shakledReadFile('tHe_WRonG_filEPAth.tXt')
    .catch(function(error) {
        console.log(error);
    });
    
// logs the error 

The callback passed into .catch() will be invoked with the argument (error) passed into reject

The Error will be passed all the way down the chain, one .catch() at the end will catch all handled errors

shakledReadFile('tHe_WRonG_filEPAth.tXt')
    .then(doubler)
    .then(resolveValue)
    .then(doubler)
    .catch(function(error) {
        console.log(error);
    });
    
// still logs the error 
At this time, this implementation of .catch() only catches handled errors that are explicitly passed to reject. Other errors may be silent. This is something I am working on fixing :)

.raceAll()

.raceAll() is an interesting built-in function that takes in an array of promises ready to be resolved and resolves the value of whichever one finishes first!

.raceAll() ignores functions in the array that do not return promises when invoked

Let me show ya:

var wait = function (time) {
    return new Shakle(function(resolve) {
        setTimeout(function () {
            resolve(time);
        }, time);
    });
 };
 
 Shakle.raceAll([wait(300), wait(100), wait(200)])
    .then(function(value) {
        console.log(value);
    });

// will log 100 only because it is the first function to resolve
I could see a possible use case for this where a client has several distributed servers it could connect to, so it pings all of them at once and connects to the one that is fastest to respond

.resolveAll()

.resolveAll() is a function similar to race, but rather than resolving only the fastest, it resolves an array containing the values from the resolution from each of the promises passed in

.resolveAll() also ignores functions in the array that do not return Promises when invoked

ALSO! The promises are resolved in 'parallel' rather than in series so the resolution will only take as long as the slowest promise to resolve

Observe:

Shakle.resolveAll([wait(200), wait(300), wait(100), wait(50), wait(150)])
  .then(function (value) {
    console.log(value)
  });
  
// will log '[50,100,150,200,300]'
handled errors are excluded from the resolved array but are not passed the .catch() callback... I'm working on this.
unexpected errors may cause .resolveAll() to never resolve... I'm working on this also.

That's about it! Thanks for checking out Shakle!