Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

first commit.

  • Loading branch information...
commit 7e60e566181a35503b08e3c5ebdc01b7a5acefc2 0 parents
Toshihiro Nakamura authored
3  .npmignore
@@ -0,0 +1,3 @@
+src/
+test/
+Jakefile
22 LICENSE
@@ -0,0 +1,22 @@
+The MIT License
+
+Copyright (c) 2011 Toshihiro Nakamura
+
+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.
116 README.md
@@ -0,0 +1,116 @@
+nue — An async control-flow library suited for the node event loop
+===================================================================
+
+nue is an async control-flow library.
+
+## Examples
+
+> JavaScript
+
+```js
+var nue = require('nue');
+
+step1();
+
+function step1() {
+ console.log('step1 start');
+ nue.parallel([
+ function(){
+ console.log('aaa');
+ },
+ function(){
+ console.log('bbb');
+ }],
+ function(err){
+ if (err) throw err;
+ console.log('step1 end\n');
+ step2();
+ }
+ );
+}
+
+function step2() {
+ console.log('step2 start');
+ nue.series([
+ function () {
+ console.log('ccc');
+ this.next('test', 2);
+ },
+ function (a, b){
+ console.log('ddd ' + a + b);
+ this.next();
+ }],
+ function (err) {
+ if (err) throw err;
+ console.log('step2 end\n');
+ step3();
+ }
+ );
+}
+
+function step3() {
+ console.log("step3 start");
+ var q = nue.parallelQueue(
+ function (data){
+ console.log('data: ' + data);
+ },
+ function (err) {
+ if (err) throw err;
+ console.log('step3 end\n');
+ step4();
+ }
+ );
+ for (var i = 0; i < 10; i++) {
+ q.push(i);
+ }
+ q.complete();
+}
+
+function step4() {
+ console.log("step4 start");
+ var q = nue.seriesQueue(
+ function (data){
+ console.log('data: ' + data);
+ this.next();
+ },
+ function (err) {
+ if (err) throw err;
+ console.log('step4 end\n');
+ }
+ );
+ for (var i = 0; i < 10; i++) {
+ q.push(i);
+ }
+ q.complete();
+}
+```
+
+> Result
+
+```
+step1 start
+aaa:
+bbb:
+step1 end
+
+step2 start
+ccc:
+ddd: test, 2
+step2 end
+
+step3 start
+data: 0
+data: 1
+data: 2
+data: 3
+data: 4
+step3 end
+
+step4 start
+data: 0
+data: 1
+data: 2
+data: 3
+data: 4
+step4 end
+```
204 lib/nue.js
@@ -0,0 +1,204 @@
+var nue = module.exports = function(tickSize) {
+ tickSize = typeof tickSize === 'number' ? tickSize : nue.tickSize;
+ return new Nue(tickSize);
+};
+var sentinel = {};
+var noOp = function () {};
+
+/**
+ *
+ * @param tickSize
+ * @param worker
+ * @param callback
+ */
+function SeriesQueue(tickSize, worker, callback) {
+ this.tickSize = tickSize;
+ this.worker = worker;
+ this.callback = callback || noOp;
+ this.values = [];
+ this.isAddingCompleted = false;
+ this.isPushed = false;
+};
+
+SeriesQueue.prototype.push = function(value) {
+ var self = this;
+ function executeBatch (args) {
+ var values = self.values.splice(0, self.tickSize);
+ if (values.length === 0) {
+ return;
+ }
+ (function execute(value, args) {
+ var context;
+ if (value === sentinel) {
+ self.callback(null);
+ return;
+ }
+ context = {
+ next: function () {
+ var args = Array.prototype.slice.apply(arguments);
+ if (values.length) {
+ execute(values.shift(), args);
+ } else {
+ process.nextTick(function () {
+ executeBatch(args);
+ });
+ }
+ },
+ end: self.callback
+ };
+ self.worker.apply(context, [value].concat(args));
+ }(values.shift(), args));
+ }
+ if (this.isAddingCompleted) {
+ throw new Error('This queue has already been frozen.');
+ }
+ this.values.push(value);
+ if (!this.isPushed) {
+ this.isPushed = true;
+ process.nextTick(function() {
+ executeBatch([]);
+ });
+ }
+};
+
+SeriesQueue.prototype.complete = function() {
+ this.push(sentinel);
+ this.isAddingCompleted = true;
+};
+
+/**
+ *
+ * @param tickSize
+ * @param tasks
+ * @param callback
+ */
+function Series(tickSize, tasks, callback) {
+ var worker = function(task) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ task.apply(this, args);
+ };
+ var queue = new SeriesQueue(tickSize, worker, callback);
+ tasks.forEach(function (task) {
+ queue.push(task);
+ });
+ queue.complete();
+};
+
+/**
+ *
+ * @param tickSize
+ * @param worker
+ * @param callback
+ */
+function ParallelQueue(tickSize, worker, callback) {
+ this.tickSize = tickSize;
+ this.worker = worker;
+ this.callback = callback || noOp;
+ this.values = [];
+ this.isAddingCompleted = false;
+ this.isCanceled = false;
+};
+
+ParallelQueue.prototype.push = function (value) {
+ var self = this;
+ function executeBatch() {
+ var context;
+ var values = self.values;
+ var value;
+ var i;
+ for (i = 0; values.length && i < self.tickSize; i++) {
+ if (self.isCanceled) {
+ break;
+ }
+ value = values.shift();
+ if (value === sentinel) {
+ self.isCompleted = true;
+ self.callback(null);
+ return;
+ }
+ context = {
+ next: noOp,
+ end: function () {
+ var args = Array.prototype.slice.apply(arguments);
+ self.callback.apply(self, args);
+ self.callback = noOp;
+ self.isCanceled = true;
+ }
+ };
+ self.worker.call(context, value);
+ }
+ }
+ if (this.isAddingCompleted) {
+ throw new Error('This queue has already been frozen.');
+ }
+ if (this.isCanceled) {
+ return;
+ }
+ this.values.push(value);
+ process.nextTick(executeBatch);
+};
+
+ParallelQueue.prototype.complete = function() {
+ this.push(sentinel);
+ this.isAddingCompleted = true;
+};
+
+/**
+ *
+ * @param tickSize
+ * @param tasks
+ * @param callback
+ */
+function Parallel(tickSize, tasks, callback) {
+ var worker = function (task) {
+ task.call(this);
+ };
+ var queue = new ParallelQueue(tickSize, worker, callback);
+ tasks.forEach(function (task) {
+ queue.push(task);
+ });
+ queue.complete();
+};
+
+/**
+ *
+ * @param tickSize
+ */
+function Nue (tickSize) {
+ this.tickSize = tickSize;
+};
+
+Nue.prototype.seriesQueue = function (worker, callback) {
+ return new SeriesQueue(this.tickSize, worker, callback);
+};
+
+Nue.prototype.series = function (tasks, callback) {
+ var args = Array.prototype.slice.apply(arguments);
+ if (!Array.isArray(args[0])) {
+ tasks = args;
+ callback = null;
+ }
+ return new Series(this.tickSize, tasks, callback);
+};
+
+Nue.prototype.parallelQueue = function (worker, callback) {
+ return new ParallelQueue(this.tickSize, worker, callback);
+};
+
+Nue.prototype.parallel = function (tasks, callback) {
+ var args = Array.prototype.slice.apply(arguments);
+ if (!Array.isArray(args[0])) {
+ tasks = args;
+ callback = null;
+ }
+ return new Parallel(this.tickSize, tasks, callback);
+};
+
+nue.DEFAULT_TICK_SIZE = 3;
+nue.name = 'nue';
+nue.version = '0.0.1';
+nue.tickSize = nue.DEFAULT_TICK_SIZE;
+nue.seriesQueue = new Nue(nue.tickSize).seriesQueue;
+nue.series = new Nue(nue.tickSize).series;
+nue.parallelQueue = new Nue(nue.tickSize).parallelQueue;
+nue.parallel = new Nue(nue.tickSize).parallel;
11 package.json
@@ -0,0 +1,11 @@
+{
+ "name" : "nue",
+ "description" : "An async control-flow library suited for the node event loop.",
+ "homepage" : "http://nakamura-to.github.com/nue/",
+ "keywords" : ["control-flow", "async"],
+ "author" : "Toshihiro Nakamura <toshihiro.nakamura@gmail.com>",
+ "contributors" : [],
+ "repository" : {"type": "git", "url": "git@github.com:nakamura-to/nue.git"},
+ "main" : "./lib/nue.js",
+ "version" : "0.0.1"
+}
75 test/spike.js
@@ -0,0 +1,75 @@
+var nue = require('../lib/nue.js');
+
+step1();
+
+function step1() {
+ console.log('step1 start');
+ nue.parallel([
+ function(){
+ console.log('aaa:');
+ },
+ function(){
+ console.log('bbb:');
+ }],
+ function(err){
+ if (err) throw err;
+ console.log('step1 end\n');
+ step2();
+ }
+ );
+}
+
+function step2() {
+ console.log('step2 start');
+ nue.series([
+ function () {
+ console.log('ccc:');
+ this.next('test', 2);
+ },
+ function (a, b){
+ console.log('ddd: ' + a + ', ' + b);
+ this.next();
+ }],
+ function (err) {
+ if (err) throw err;
+ console.log('step2 end\n');
+ step3();
+ }
+ );
+}
+
+function step3() {
+ console.log("step3 start");
+ var q = nue.parallelQueue(
+ function (data){
+ console.log('data: ' + data);
+ },
+ function (err) {
+ if (err) throw err;
+ console.log('step3 end\n');
+ step4();
+ }
+ );
+ for (var i = 0; i < 5; i++) {
+ q.push(i);
+ }
+ q.complete();
+}
+
+function step4() {
+ console.log("step4 start");
+ var q = nue.seriesQueue(
+ function (data){
+ console.log('data: ' + data);
+ this.next();
+ },
+ function (err) {
+ if (err) throw err;
+ console.log('step4 end\n');
+ }
+ );
+ for (var i = 0; i < 5; i++) {
+ q.push(i);
+ }
+ q.complete();
+}
Please sign in to comment.
Something went wrong with that request. Please try again.