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

flasync

v0.2.3

Published

A simple helper library for authors of fluent asynchronous APIs.

Downloads

34

Readme

flasync

A simple helper mix-in for authors of fluent asynchronous APIs.

Writing an API with flasync

Writing a fluent API with flasync is very close to writing a regular fluent JavaScript object. The differences are that the flasync library has to be mixed-in by doing a flasync(this) in your constructor.

All synchronous methods have to be wrapped in a call to this.asyncify, and all asynchronous methods must be wrapped with this.async. There's no constraint on the signature of synchronous methods (except that they must return this, being fluent). Asynchronous methods must take a callback as their last parameter.

Here's an example of a simple API that can write to the console a text literal using the write method, and dump the contents of a file to the console:

'use strict';
var flasync = require('flasync');
var fs = require('fs');

var Dump = function Dump() {
  flasync(this);
  var self = this;

  this.write = this.asyncify(
    this._write = function(text) {

    Console.log(text);
    return this;
  });

  this.fromFile = this.async(
    this._fromFile = function(path, next) {
    
    fs.readFile(path, function (err, text) {
      if (err) {
        next(err);
        return;
      }
      self._write(text);
      next();
    });
    return this;
  });
};

Notice how the fromFile method calls the non-asynchronified private version of write, to avoid wasteful and unclear asynchronous calls to a method that does not require to be called asynchronously. Methods that need to call other methods should do the same. Internally, methods should always call the private versions of other methods.

The then and finally methods are added to the object when applying the mix-in.

Using an API built with flasync

Here's some sample code using the API defined in the previous section:

var Dump = require('./lib/dump');

var dump = new Dump();

dump
  .write('The file readme.txt contains:')
  .fromFile('readme.txt')
  .write('End of file...')
  .then(function(next) {
    // do something else
    next();
  })
  .finally(function() {
    // do one final thing
  });

The output of this program looks like this:

The file readme.txt contains:
Lorem ipsum dolor sit amet
End of file...

As you can see, the output order is the same as the calling order, despite the fact that fromFile is asynchronous, and write is not. That means that the second write call has been transformed into an asynchronous method call, so that it can happen after the file read has called back.

Also notice that no callback function is present, as the method chaining gives enough information about the desired outcome.

The then method has been provided by flasync. Then blocks can be inserted at any stage of the call chain.

The finally method should be used when terminating a chain of calls. It doesn't mean the API can't be used after this has been called, but it shouldn't be used until the callback function has been called. By design, the finally method is not fluent.

Error handling

Errors should be thrown from methods like usual. If the user of your API provided an onError handler, that handler will receive the error as its parameter. If no error handler is specified, the error will bubble up the stack. Because of asynchrony however, the API user should not count on being able to try/catch those exceptions, and should use an error handler instead, unless the desired behavior is for the errors to bubble up the stack to a global error handler for the application.

dump.onError(function(err) {
  // Do something with the error
})

The error handler has to be added before the throwing method is called.

Blog posts about this library

For more info...

  1. API Requirements
  2. Building an API
  3. The helper library
  4. Nope, Q won't work
  5. Internally calling methods
  6. Recursive calls