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

argyll

v1.4.0

Published

Asynchronous Result Gathering

Downloads

7

Readme

Argyll (Asynchronous Result Gathering)

Build Status

Argyll is a simple little library that allows you to parallelize the process of gathering asynchronous results. I wrote it because I was performing complex workflows using Promises that didn't truly need to be serialized. Where this library is most useful is enabling you to perform multiple parallel calls, only triggering callbacks when the callback's result dependencies are satisfied.

A basic bogus skeletal example:

var Argyll = require('argyll');

Argyll.start(makingRequests)
      .always(acceptEverything)
      .always(acceptTemplate)
      .maybe(handleError);

function makingRequests(g) {
  // Make some calls all at once, the g.gather() function
  // creates an intercept proxy that routes the responses
  // appropriately
  User.findById(someUserId, g.gather('err!', 'user?'));
  Profile.findById(someProfileId, g.gather('err!', 'profile?'));
  Logs.findAll(someUserId, g.gather('err!', 'logs'));
}

function acceptEverything(g, user, profile, logs) {
  // We'll only get here when all three results have been
  // fully resolved, even though they were resolved using
  // three separate asynchronous calls
  var result = processTemplate(g.data());
  
  // 'provide' will allow you to explicitly satisfy a 
  // result dependency. 'template' is the result name
  // that will be fulfilled
  g.provide('template', result);

  // We could have also written:
  //     return processTemplate(g.data());
  // and then just registered this callback using:
  //     always(acceptEverything).returning('template')
}

function acceptTemplate(template) {
  // You'll notice this function doesn't take a 'g' 
  // argument and it still works perfectly fine.
  res.end(template);
}

function handleError(g, err) {
  // Uh-oh!  Ignore any subsequent calls
  g.cancel();
}

You'll notice that the creation of the gathering chain didn't specify which results the functions were in charge of gathering. This is because the values are extracted from the Function's signature. All of the argument names are treated as the result names to gather. You can also specify them explicitly if you like:

Argyll.start(makingRequests)
      .always(acceptEverything, 'g', 'user', 'profile', 'logs')
      .always(acceptTemplate, 'template')
      .maybe(handleError, 'g', 'err');

What you may have not noticed is that the order in which you register callbacks actually doesn't matter much. Argyll will invoke a callback as soon as all of its dependencies have been satisfied, regardless of its order in the gathering context's definition, and regardless of whether or not a callback defined earlier has been triggered.

The API

The value returned by require('argyll') is a function that can be used to create a gathering context. It also exposes some immediate child functions for kicking things off. They are always(), maybe(), requires() and start(). These functions behave exactly as the ones exposed by the gathering context except that they also create a context.

Another function withContextName({String} contextName) sets the name of the Argyll gathering context. This is the result name as it will be provided to callbacks that accept it. By default, it is 'g'. Synonyms include setContextName(). This function can only be used to kick things off.

argyll([{String} contextName], [{Object} defaults]) - creates and returns a new gathering context. The previous chain could have been written as follows, making the separate makingRequests function unnecessary:

var argyll = require('argyll');
var g = argyll();
g.always(acceptEverything);
g.always(acceptTemplate);
g.maybe(handleError);

User.findById(someUserId, g.gather('err!', 'user?'));
Profile.findById(someProfileId, g.gather('err!', 'profile?'));
Logs.findAll(someUserId, g.gather('err!', 'logs'));

The gathering context contains the following functions:

data() - returns an Object containing the results collected thus far by the gathering context.

start({Function} callback) - Register a callback to be used to kick things off. This callback will only take a reference to the gathering context. Synonyms include onStart() and startsWith().

always({Function} callback, {String*} resultNames) - Registers a callback to be fired when its dependent results have been resolved. If no resultNames are specified, they will be extracted from the callback Function arguments. Results gathered with this callback are considered necessary in reporting completion. Synonyms include must().

maybe({Function} callback, {String*} resultNames) - Registers a callback to be fired when its dependent results have been resolved. If no resultNames are specified, they will be extracted from the callback Function arguments. Results gathered with this callback are considered optional in reporting completion, making it good for error handlers. Synonyms include sometimes().

complete({Function} callback) - Register a callback to be called when the gathering context has no pending required results to gather. Synonyms include onComplete(), whenComplete() and completesWith().

requires({String*} resultNames) - Instructs the gathering context that the specified resultNames are required to trigger a completion callback, even if no explicit interest is registered by other functions. Synonyms include require().

provide({String} resultName, {Mixed} value) - Explicitly provide a named result value.

cancel() - Cancels all pending callbacks. Useful if you want to short-circuit the process upon an error.

gather({String*} resultNames) - Generates a node-compatible callback that can be used to automatically provide results (including errors). If the result names are suffixed with a question mark (?) then null values will be accepted (undefined will never be accepted). If the result names are suffixed with an exclamation mark (!), then a provided result will short-circuit any subsequent argument processing. Synonyms include callback().

receives({String} resultName) - Generates a 'receives' callback that can be passed to the complete() method of another gathering context. When that context has completed gathering all of its data, it will provide that data to the specified resultName of this gathering context.

contextName() - Returns the name of the Argyll gather context as it will be provided to callbacks that accept it. By default, it is 'g'. Synonyms include getContextName().

returning({String} resultName) - Can be applied to always() and maybe() registrations. This tells Argyll that the callback returns a value that provides the specified resultName. Synonyms include returns().

throwing({String} resultName) - Can be applied to always() and maybe() registrations. This tells Argyll that the callback may throw an Exception, the value of which provides the specified resultName. Synonyms include throws().

Installing

To install from NPM (Node Package Manager), type:

npm install argyll

Resources

For the latest releases, see the Argyll GitHub Page

License (MIT License)

Copyright (c) 2014, 2015 Thomas S. Bradford

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.