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 🙏

© 2025 – Pkg Stats / Ryan Hefner

sync-builder

v0.9.1

Published

Wrapper to run asynchronous code in a synchronous way.

Readme

sync-builder Build Status

Wrapper to run asynchronous code in a synchronous way.

Let you transform this:

utils.async().then(function() {
  utils.sync();
  return utils.async();
}).then(function() {
  return utils.async();
}).then(function() {
  utils.sync();
}).then(function() {
  console.log("done");
});

into this:

new SyncBuilder(utils)
  .async()
  .sync()
  .async()
  .async()
  .sync()
  .build(function() {
    console.log("done");
  });

Installation

bower

$ bower sync-builder --save

and include lib/sync-builder.js or lib/sync-builder.min.js and use it globally (SyncBuilder) or using AMD or CommonJS (sync-builder).

npm

$ npm install sync-builder --save

and use it:

var SyncBuilder = require('sync-builder');

Download

Download the source file: sync-builder.js or production version: sync-builder.min.js.

Example

var utils = {

  async: function() {
    return new Promise(function(resolve) {
      setTimeout(function() {
        console.log("async");
        resolve();
      }, 0);
    });
  },

  sync: function() {
    console.log("sync")
  }

};

var builder = SyncBuilder(utils);
builder
  .async()
  .sync()
  .async()
  .async()
  .sync()
  .build(function() {
    console.log("done");
  });

Expected output order:

async
sync
async
async
sync
done

To achieve the same without SyncBuilder:

utils.async().then(function() {
  utils.sync();
  return utils.async();
}).then(function() {
  return utils.async();
}).then(function() {
  utils.sync();
}).then(function() {
  console.log("done");
});

Wrap your object instance

Let's consider John, who has to work to earn money. John spends 1 second to get 500 cents:

var Person = function(budget, salary) {
  this.budget = budget;
  this.salary = salary;
};
Person.prototype = {
  goToWork: function() {
    return new Promise(function(resolve) {
      setTimeout(function() {
        this.budget += this.salary;
        resolve();
      }.bind(this), 1000);
    }.bind(this));
  },
  printBudget: function() {
    console.log(this.budget);
  }
};

If we run code synchronously, we don't get desired results:

var johnKowalski = new Person(1000, 500);
johnKowalski.goToWork(); // adds 500 to budget after 1 second
johnKowalski.printBudget(); // prints 1000 immediately

Using the wrapper, we get the expected result:

var johnKowalski = new Person(1000, 500);
var builder = new SyncBuilder(johnKowalski);
builder
  .goToWork()
  .printBudget()
  .build(); // prints 1500 after 1 second

Motivation

I had a set of utils method to test my component:

// given component
var testUtils = {
  checkWidth: function(width) {
    equal(component.width, width);
  },
  click: function() {
    component.click(); // async, ready on 'ready' event
  },
  move: function(x) {
    component.move(); // async, ready on 'moved' event
  }
}

To get it working, I had to use promises:

// given component
var testUtils = {
  checkWidth: function(width) {
    equal(component.width, width);
  },
  click: function() {
    component.click(); // async

    return new Promise(function(resolve) {
      component.on('ready', function() {
        resolve();
      }
    });
  },
  move: function(x) {
    component.move(); // async

    return new Promise(function(resolve) {
      component.on('moved', function() {
        resolve();
      });
    });
  }
}

The best I could do with then chaining was:

testUtils.checkWidth(100);
testUtils.click().then(function() {
  testUtils.checkWidth(100);
  return testUtils.move();
}).then(function() {
  testUtils.checkWidth(150);
  return testUtils.click();
}).then(function() {
  testUtils.checkWidth(100);
});

which is not bad but clearly not readable... Using SyncBuilder, we can achieve the same functionality in a readable way:

var testUtilsBuilder = new SyncBuilder(testUtils);
testUtilsBuilder
  .checkWidth(100)
  .click()
  .checkWidth(100)
  .move()
  .checkWidth(150)
  .click()
  .checkWidth(150)
  .build();

Isn't it more understandable? :)

API

SyncBuilder wraps all the methods from your object (whether it's a literal or an instance) and make it public to you.

If you want to create synchronous function, you should not return anything. If you want to create a asynchronous function, you should return a Promise. The only requirement for being a Promise is to have a then function that is called after your asyncronous code was run.

var utils = {
  sync: function() {
    // your code
  },
  async: function() {
    // your async code
    return promise;
  }
}

Don't forget to call build() method at the end!

new SyncBuilder().async().sync().build();

build() method itself takes a callback to be called after all the methods:

new SyncBuilder().async().sync().build(function() {
  console.log("I'm done");
});

You can pass a context and arguments to build() method as well:

new SyncBuilder().async().sync().build(function(a1, a2) {
  // this === context
  // a1 === arg1
  // a2 === arg2
  console.log("I'm done");
}, context, arg1, arg2);

Arguments

You can pass arguments to your functions:

var utils = {

  async: function(text) {
    return new Promise(function(resolve) {
      setTimeout(function() {
        console.log(text);
        resolve();
      }, 0);
    });
  },

  sync: function(text, number) {
    console.log(text, number)
  }

};

new SyncBuilder(utils)
  .async("I'm asynchronous")
  .sync("Sync here", 1)
  .sync("Again sync", 2)
  .build();

the result:

I'm asynchronous
Sync here 1
Again sync 2

Promises

In the examples, I used ES6 Promises syntax. Here is which browsers support it at the moment: http://kangax.github.io/compat-table/es6/#Promise.

You can use any other library like q or jQuery promise.