Skip to content
This repository has been archived by the owner on Dec 7, 2020. It is now read-only.

Commit

Permalink
v0.3.0-a: added iterable-sequences, closes #4, added 'promise(..)', c…
Browse files Browse the repository at this point in the history
…loses #10. split 'contrib' into another package, closes #11.
  • Loading branch information
getify committed Jan 1, 2014
1 parent 92e9bd9 commit 78a45ec
Show file tree
Hide file tree
Showing 14 changed files with 771 additions and 169 deletions.
1 change: 1 addition & 0 deletions .npmignore
@@ -1,2 +1,3 @@
.gitignore
node_modules
contrib
394 changes: 257 additions & 137 deletions README.md

Large diffs are not rendered by default.

25 changes: 24 additions & 1 deletion asq.src.js
@@ -1,5 +1,5 @@
/*! asynquence
v0.2.0-c (c) Kyle Simpson
v0.3.0-a (c) Kyle Simpson
MIT License: http://getify.mit-license.org
*/

Expand Down Expand Up @@ -410,6 +410,28 @@
return sequence_api;
}

function promise() {
if (seq_error || seq_aborted || arguments.length === 0) {
return sequence_api;
}

ARRAY_SLICE.call(arguments)
.forEach(function __foreach__(pr){
then(function __then__(done){
// check if this argument is a non-thennable function, and
// if so, assume we shold invoke it to return a promise
// NOTE: `then` duck-typing of promises is stupid.
if (typeof pr === "function" && !("then" in pr)) {
pr = pr.apply(ø,ARRAY_SLICE.call(arguments,1));
}
// now, hook up the promise to the sequence
pr.then(done,done.fail);
});
});

return sequence_api;
}

function abort() {
if (seq_error) {
return sequence_api;
Expand Down Expand Up @@ -476,6 +498,7 @@
pipe: pipe,
seq: seq,
val: val,
promise: promise,
abort: abort
})
;
Expand Down
1 change: 1 addition & 0 deletions contrib/.npmignore
@@ -0,0 +1 @@
node_modules
38 changes: 30 additions & 8 deletions contrib/README.md
@@ -1,6 +1,6 @@
# asynquence Contrib

Optional plugin helpers are provided (`contrib.js` is *just* **846 bytes** minzipped) in `/contrib/*`.
Optional plugin helpers are provided in `/contrib/*`. The full bundle of plugins (`contrib.js`) is **~1.3k** minzipped.

Gate variations:

Expand All @@ -15,9 +15,21 @@ Sequence-step variations:
* `until(..)` is like `then(..)`, except it **keeps re-trying until success** or `break()` (for loop semantics) before the main sequence proceeds.
* `try(..)` is like `then(..)`, except it proceeds as success on the main sequence **regardless of success/failure signal**. If an error is caught, it's transposed as a special-format success message: `{ catch: ... }`.

### `iterable-sequence` Plugin
`iterable-sequence` plugin provides `ASQ.iterable()` for creating iterable sequences. See [Iterable Sequences](https://github.com/getify/asynquence/blob/master/README.md#iterable-sequences) for more information.

## Using Contrib Plugins

Include the `contrib.js` (or `contrib.src.js`) file along with the *asynquence* library file. This automatically extends the API with the plugins.
In the browser, include the `contrib.js` file along with the *asynquence* library file (`asq.js`). Doing so automatically extends the API with the plugins.

In node.js, you install the `asynquence-contrib` package alongside the `asynquence` package, and `require(..)` both of them, in order:

```js
var ASQ = require("asynquence");
require("asynquence-contrib");
```

**Note:** The `asynquence-contrib` module has no API (it only attaches itself to the `asynquence` package), so just calling `require(..)` without storing its return value is sufficient and recommended.

They can then be used directly, like this:

Expand All @@ -30,14 +42,24 @@ ASQ()

## Building Contrib Bundle

There is a utility provided to bundle the contrib plugins and build the un-minified and minified files from the bundle.
There is a utility provided to bundle the contrib plugins.

`bundle.js` builds the unminified bundle `contrib.src.js`, and then builds (minifies) `contrib.js`. The recommended way to invoke this utility is via npm:

`npm run-script bundle`

By default, the build includes all the `contrib/plugin.*` plugins. But, you can manually specify which plugins you want, by name, like this:

```
./bundle.js any none try
```

`contrib/bundle.js` builds `contrib.src.js` (in the package root), and then builds (minifies) `contrib.js` (in the package root). The recommended way to invoke this utility is via npm:
This would bundle only the `any`, `none`, and `try` plugins.

`npm run-script bundle-contrib`
**Note:** `npm run-script ..` [doesn't *currently*](https://github.com/isaacs/npm/issues/3494) support passing the extra command line parameters, so you must use `./bundle.js` **instead of** `npm run-script bundle` if you want to pick which specific plugins to bundle.

By default, the build includes all the `contrib/plugin.*` plugins. You can manually specify which plugins you want, like this:
## License

`contrib/bundle.js any none try` (which would bundle only `any`, `none`, and `try` plugins)
The code and all the documentation, unless otherwise noted, are released under the MIT license.

**Note:** `npm run-script ..` [doesn't *currently*](https://github.com/isaacs/npm/issues/3494) support passing the extra command line params, so you must use `contrib/bundle.js` instead of `npm run-script bundle-contrib` if you want to pick which plugins to bundle.
http://getify.mit-license.org/
8 changes: 4 additions & 4 deletions contrib/bundle.js
Expand Up @@ -21,7 +21,7 @@ function bundlePlugins(dir) {

bundle_str += fs.readFileSync(path.join(dir,file),{ encoding: "utf8" });
}
else if (st.isDirectory()) {
else if (st.isDirectory() && !/node_modules/.test(file)) {
bundlePlugins(path.join(dir,file));
}
});
Expand Down Expand Up @@ -56,7 +56,7 @@ bundlePlugins(
bundle_wrapper = bundle_wrapper.replace(/\/\*PLUGINS\*\//,function(){ return bundle_str; });

fs.writeFileSync(
path.join(__dirname,"..","contrib.src.js"),
path.join(__dirname,"contrib.src.js"),
bundle_wrapper,
{ encoding: "utf8" }
);
Expand All @@ -65,7 +65,7 @@ console.log("Built contrib.src.js.");
console.log("Minifying to contrib.js.");

try {
result = ugly.minify(path.join(__dirname,"..","contrib.src.js"),{
result = ugly.minify(path.join(__dirname,"contrib.src.js"),{
mangle: true,
compress: true,
output: {
Expand All @@ -74,7 +74,7 @@ try {
});

fs.writeFileSync(
path.join(__dirname,"..","contrib.js"),
path.join(__dirname,"contrib.js"),
result.code + "\n",
{ encoding: "utf8" }
);
Expand Down
6 changes: 3 additions & 3 deletions contrib/contrib-wrapper.js
@@ -1,13 +1,13 @@
/*! asynquence
v0.2.0-c (c) Kyle Simpson
/*! asynquence-contrib
v0.1.0-a (c) Kyle Simpson
MIT License: http://getify.mit-license.org
*/

(function UMD(dependency,definition){
if (typeof module !== "undefined" && module.exports) { module.exports = definition(require(dependency)); }
else if (typeof define === "function" && define.amd) { define([dependency],definition); }
else { definition(dependency); }
})(this.ASQ || "./asq.src.js",function DEF(ASQ){
})(this.ASQ || "asynquence",function DEF(ASQ){
"use strict";

var ARRAY_SLICE = Array.prototype.slice,
Expand Down
26 changes: 26 additions & 0 deletions contrib/node-tests.js
@@ -0,0 +1,26 @@
#!/usr/bin/env node

function doneLogMsg(msg) {
return function() {
console.log(msg);
};
}

var ASQ = require("asynquence");
var path = require("path");
require(path.join(__dirname,"contrib.src.js"));
var tests = require(path.join(__dirname,"tests.js"))(doneLogMsg);

console.log("asynquence-contrib test suite");

ASQ.apply(ASQ,tests)
.val(doneLogMsg("ALL CONTRIB TESTS PASSED!"))
.or(function(){
doneLogMsg("*** TEST SUITE FAILURE ***")();
for (var i=0; i<arguments.length; i++) {
doneLogMsg(arguments[i] +
(arguments[i] && arguments[i].stack ? arguments[i].stack : "")
)();
}
process.exit(1); // non-zero exit code!
});
33 changes: 33 additions & 0 deletions contrib/package.json
@@ -0,0 +1,33 @@
{
"name": "asynquence-contrib",
"version": "0.1.0-a",
"description": "contrib plugins for asynquence",
"main": "./contrib.js",
"scripts": {
"test": "./node-tests.js",
"bundle": "./bundle.js"
},
"devDependencies": {
"asynquence": "latest",
"uglify-js": "~2.4.8"
},
"repository": {
"type": "git",
"url": "git://github.com/getify/asynquence.git"
},
"keywords": [
"async",
"flow-control",
"sequences",
"promise",
"iterator",
"generator"
],
"bugs": {
"url": "https://github.com/getify/asynquence/issues",
"email": "getify@gmail.com"
},
"homepage": "https://github.com/getify/asynquence/blob/master/contrib",
"author": "Kyle Simpson <getify@gmail.com>",
"license": "MIT"
}
157 changes: 157 additions & 0 deletions contrib/plugin.iterable-sequence.js
@@ -0,0 +1,157 @@
// "ASQ.iterable()"
ASQ.iterable = function __iterable__() {
var sequence_api,
ARRAY_SLICE = Array.prototype.slice,
brand = "__ASQ__", ø = Object.create(null),

seq_error = false,
seq_aborted = false,

seq_tick,

val_queue = [],
or_queue = [],

sequence_errors = []
;

function schedule(fn) {
return (typeof setImmediate !== "undefined") ?
setImmediate(fn) : setTimeout(fn,0)
;
}

function notifyErrors() {
var fn;

seq_tick = null;

while (or_queue.length > 0) {
fn = or_queue.shift();
try {
fn.apply(ø,sequence_errors);
}
catch (err) {
if (checkBranding(err)) {
sequence_errors = sequence_errors.concat(err);
}
else {
sequence_errors.push(err);
if (err.stack) { sequence_errors.push(err.stack); }
}
if (or_queue.length === 0) {
console.error.apply(console,sequence_errors);
}
}
}
}

function val() {
if (seq_error || seq_aborted || arguments.length === 0) {
return sequence_api;
}

val_queue.push.apply(val_queue,arguments);

return sequence_api;
}

function or() {
if (seq_aborted || arguments.length === 0) {
return sequence_api;
}

or_queue.push.apply(or_queue,arguments);

return sequence_api;
}

function next() {
var ret = { value: undefined, done: true };

if (seq_error || seq_aborted) {
throwErr("Sequence cannot be iterated");
return ret;
}

if (val_queue.length > 0) {
try {
ret.value = val_queue.shift().apply(ø,arguments);
}
catch (err) {
if (ASQ.isMessageWrapper(err)) {
throwErr.apply(ø,err);
}
else if (err.stack) {
throwErr(err,err.stack);
}
else {
throwErr(err);
}
}
ret.done = (val_queue.length === 0);
}

return ret;
}

function throwErr() {
if (seq_error || seq_aborted) {
return sequence_api;
}

sequence_errors.push.apply(sequence_errors,arguments);
seq_error = true;
if (!seq_tick) {
seq_tick = schedule(notifyErrors);
}

return sequence_api;
}

function abort() {
if (seq_error || seq_aborted) {
return;
}

seq_aborted = true;

clearTimeout(seq_tick);
seq_tick = null;
val_queue.length = 0;
or_queue.length = 0;
sequence_errors.length = 0;
}


// ***********************************************
// Object branding utilities
// ***********************************************
function brandIt(obj) {
Object.defineProperty(obj,brand,{
enumerable: false,
value: true
});

return obj;
}


// ***********************************************
// Setup the ASQ.iterable() public API
// ***********************************************
sequence_api = brandIt({
val: val,
then: val,
or: or,
next: next,
"throw": throwErr,
abort: abort
});

// treat ASQ.iterable() constructor parameters as having been
// passed to `val()`
sequence_api.val.apply(ø,arguments);

return sequence_api;
};

0 comments on commit 78a45ec

Please sign in to comment.