{"_id":"sl-task-emitter","_rev":"72-533bb6af33d535333e13ac7ff1cc1e1b","name":"sl-task-emitter","dist-tags":{"latest":"0.0.3"},"versions":{"0.0.1":{"name":"sl-task-emitter","version":"0.0.1","author":{"name":"Ritchie Martori"},"_id":"sl-task-emitter@0.0.1","maintainers":[{"name":"faisal","email":"faisal@faisal.com"}],"dist":{"shasum":"840e2cbed465c386caf6c426cc09b89913679e71","tarball":"https://registry.npmjs.org/sl-task-emitter/-/sl-task-emitter-0.0.1.tgz","integrity":"sha512-Tvjj3khrED5KTLsKUeWn3jLt28N+qWfjSOz/t9XL2p+FPtd4ikLkUH9jxFk+jvlcCoTg2iuk1ynpz9FzImc2AA==","signatures":[{"sig":"MEUCIQDQ7GkAEDUhKfDYSydOdyQ4StLsaXjlP+OOhOr8s9JNngIgEri6swtgMZCyBZeIymKE1pZy4sTz33KAxJ84dmq3KPE=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"_from":"sl-task-emitter","scripts":{"test":"mocha"},"_npmUser":{"name":"faisal","email":"faisal@faisal.com"},"_npmVersion":"1.2.21","description":"Perform an unkown number of tasks recursively and in parallel.","directories":{},"dependencies":{"debug":"latest"},"devDependencies":{"mocha":"latest"}},"0.0.2":{"name":"sl-task-emitter","version":"0.0.2","author":{"name":"Ritchie Martori"},"_id":"sl-task-emitter@0.0.2","maintainers":[{"name":"faisal","email":"faisal@faisal.com"},{"name":"strongloop","email":"callback@strongloop.com"},{"name":"ritch","email":"skawful@gmail.com"}],"dist":{"shasum":"e45b7f784b3469b1ab7864efe79bfd9b0b393033","tarball":"https://registry.npmjs.org/sl-task-emitter/-/sl-task-emitter-0.0.2.tgz","integrity":"sha512-vFxU2KxMcEOvhksvXOFnK0bwrNvJcPyZ5hMgMPLVznnJ/qAjTlqLAOefn1TxRFOUvKDSZk1lGAymePpzOOHS8g==","signatures":[{"sig":"MEUCIGyjfPnctbXBcRDhOznyzkwj91Lj642hUB+Lxex6/F4eAiEAwNW82xEeZ1lKYxxWKlOe7sqvOTYDYUVXvq7Kw9szhLw=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"_from":"sl-task-emitter","scripts":{"test":"mocha"},"_npmUser":{"name":"faisal","email":"faisal@faisal.com"},"_npmVersion":"1.2.21","description":"Perform an unkown number of tasks recursively and in parallel.","directories":{},"dependencies":{"debug":"latest"},"devDependencies":{"mocha":"latest"}},"0.0.3":{"name":"sl-task-emitter","version":"0.0.3","author":{"name":"Ritchie Martori"},"license":"Apache 2","_id":"sl-task-emitter@0.0.3","maintainers":[{"name":"faisal","email":"faisal@faisal.com"},{"name":"strongloop","email":"callback@strongloop.com"},{"name":"ritch","email":"skawful@gmail.com"}],"dist":{"shasum":"9dc343b301ae95c63236b0214590f09f7a6c9aa6","tarball":"https://registry.npmjs.org/sl-task-emitter/-/sl-task-emitter-0.0.3.tgz","integrity":"sha512-3QukTiTBEw00kLHKWzx91Cb6mLHPtm5Vtdp5YmVgwcUiuFbKcTl/MI+KxwaApy2wFMHZb23trJ9cEVd+zDXS8A==","signatures":[{"sig":"MEUCIQCjVDL9vQSjsQvZyIVP207VwzsOxzZZ3rXY6N4cFw3s4wIgLrPUqo8VBa5ctHsrSYUgGkmhj/1lj/6zi142hmVd594=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}]},"_from":".","scripts":{"test":"mocha"},"_npmUser":{"name":"ritch","email":"skawful@gmail.com"},"repository":{"url":"http://github.com/strongloop/sl-task-emitter.git","type":"git"},"_npmVersion":"1.2.15","description":"Perform an unknown number of tasks recursively and in parallel.","directories":{},"dependencies":{"debug":"latest"},"devDependencies":{"mocha":"latest"}}},"time":{"created":"2013-05-20T00:29:13.689Z","modified":"2026-04-14T15:16:04.443Z","0.0.1":"2013-05-20T00:29:15.108Z","0.0.2":"2013-05-20T23:19:50.321Z","0.0.3":"2013-06-07T18:16:20.422Z"},"author":{"name":"Ritchie Martori"},"license":"Apache 2","repository":{"url":"http://github.com/strongloop/sl-task-emitter.git","type":"git"},"description":"Perform an unknown number of tasks recursively and in parallel.","maintainers":[],"readme":"# sl-task-emitter\nv0.0.1\n\n## Install\n\n    slnode install sl-task-emitter\n\n## Purpose\n\nPerform an unkown number of tasks recursively and in parallel. For example, reading all the files in a nested set of directories. Built in support for [domains](http://nodejs.org/api/domain.html) by inheriting directly from `EventEmitter`.\n    \n## Example\n\nThe following example shows the basic API for a TaskEmitter.\n\n    var TaskEmitter = require('../');\n    var request = require('request');\n    var results = [];\n\n    var te = new TaskEmitter();\n\n    te\n      .task('request', request, 'http://google.com')\n      .task('request', request, 'http://yahoo.com')\n      .task('request', request, 'http://apple.com')\n      .task('request', request, 'http://youtube.com')\n      // listen for when a task completes by providing the task name\n      .on('request', function (url, res, body) {\n        results.push(Buffer.byteLength(body));\n      })\n      .on('progress', function (status) {\n        console.log(((status.total - status.remaining) / status.total) * 100 + '%', 'complete');\n      })\n      .on('error', function (err) {\n        console.log('error', err);\n      })\n      .on('done', function () {\n        console.log('Total size of all homepages', results.reduce(function (a, b) {\n          return a + b;\n        }), 'bytes');\n      });\n\nThe next example highlights how TaskEmitter can be used to simplify recursive asynchronous operations. The following code recursively walks a social network over HTTP. All requests run in parallel.\n\n    var TaskEmitter = require('../');\n    var request = require('request');\n    var socialNetwork = [];\n\n    var te = new TaskEmitter();\n\n    te\n      // specify a task name\n      .task('friends', fetch, 'me')\n      .on('friends', function (user, url) {\n        if(url !== 'me') {\n          socialNetwork.push(user);\n        }\n    \n        user.friendIds.forEach(function (id) {\n          this.task('friends', fetch, 'users/' + id)\n        }.bind(this));\n      })\n      .on('done', function () {\n        console.log('There are a total of %n people in my network', socialNetwork.length);\n      });\n\n\n    function fetch(url, fn) {\n      request({\n        url: 'http://my-api.com/' + url,\n        json: true,\n        method: 'GET'\n      }, fn);\n    }\n\n## Extending TaskEmitter\n\n`TaskEmitter` is designed to be a base class which can be inherited from and extended by many levels of sub classes. The following example shows a class that inherits from TaskEmitter and provides recursive directory walking and file loading.\n\n    var TaskEmitter = require('../');\n    var fs = require('fs');\n    var path = require('path');\n    var inherits = require('util').inherits;\n\n    function Loader() {\n      TaskEmitter.call(this);\n  \n      this.path = path;\n      this.files = {};\n\n      this.on('readdir', function (p, files) {\n        files.forEach(function (f) {\n          this.task(fs, 'stat', path);\n        }.bind(this));\n      });\n\n      this.on('stat', function (file, stat) {\n        if(stat.isDirectory()) {\n          this.task(fs, 'readdir', file);\n        } else {\n          this.task(fs, 'readFile', file, path.extname(file) === '.txt' ? 'utf-8' : null);\n        }\n      });\n\n      this.on('readFile', function (path, encoding, data) {\n        this.files[path] = data;\n      });\n    }\n\n    inherits(Loader, TaskEmitter);\n\n    Loader.prototype.load = function (path, fn) {\n      if(fn) {\n        // error events are handled if a task callback ever is called\n        // with a first argument that is not falsy\n        this.on('error', fn);\n    \n        // once all tasks are complete the done event is emitted\n        this.on('done', function () {\n          fn(null, this.files);\n        });\n      }\n  \n      this.task(fs, 'readdir', path);\n    }\n\n    // usage\n    var l = new Loader();\n    \n    l.load('sample-files', function (err, files) {\n      console.log(err || files);\n    });\n\n## API\n\n### taskEmitter.task()\n\nExecute a task and emit an event when it is complete.\n\nYou must provide\n\n  - A `scope` (eg. the fs module) and a name of a function on the scope (eg. `'readFile'`).\n\n**Example**\n\n    var fs = require('fs');\n    var te = new TaskEmitter();\n\n    te\n      .task(fs, 'readFile')\n      .on('readFile', ...);\n  \nor\n\n  - Your task name (eg. 'my-task') and a function that executes the task and takes a conventional node callback (`fn(err, result)`).\n  \n**Example**\n\n    var te = new TaskEmitter();\n\n    te\n      .task('my-task', myTask)\n      .on('my-task', ...);\n      \n    function myTask(fn) {\n      // an async task of some sort\n      setTimeout(function() {\n        // callback\n        fn(null, 'my result');\n      }, 1000);\n    }\n    \n**Example**\n\nIt is safe to execute tasks in the event listener of another task as long as it is in the same tick.\n\n    var te = new TaskEmitter();\n\n    te\n      .task(fs, 'stat', '/path/to/file-1')\n      .task(fs, 'stat', '/path/to/file-2')\n      .task(fs, 'stat', '/path/to/file-3')\n      .on('stat', function(err, path, stat) {\n        if(stat.isDirectory()) {\n          // must add tasks before\n          // this function returns\n          this.task(fs, 'readdir', path);\n        }\n      })\n      .on('readdir', function(path, files) {\n        console.log(files); // path contents\n      })\n      .on('done', function() {\n        console.log('finished!');\n      });\n    \n### taskEmitter.remaining()\n\nDetermine how many tasks remain.\n\n**Example**\n\n    var te = new TaskEmitter();\n\n    te\n      .task(fs, 'stat', '/path/to/file-1')\n      .task(fs, 'stat', '/path/to/file-2')\n      .task(fs, 'stat', '/path/to/file-3')\n      .on('stat', function(err, path, stat) {\n        console.log('%s is a %s', stat.isDirectory() ? 'directory' : 'file');\n      })\n      .on('done', function() {\n        console.log('finished!');\n      });\n      \n    var remaining = te.remaining();\n    \n    console.log(remaining); // 3\n\n### taskEmitter.stop()\n\nStop all remaining tasks.\n\n### taskEmitter.reset()\n\nRemove all tasks and listeners.\n    \n## Events\n\n### <taskName>\n  \nEmitted when the `<taskName>` has completed.\n  \n**Example:**\n\n    var te = new TaskEmitter();\n\n    te\n      .task('foo', function(arg1, arg2, fn) {\n        var err, result = 'foo';\n    \n        fn(err, result);\n      })\n      .on('error', ...)\n      .on('foo', function(arg1, arg2, result) {\n        // ...\n      });\n\n**Example using the `fs` module**\n\n    var te = new TaskEmitter();\n    \n    te\n      .task(fs, 'stat', '/path/to/file-1')\n      .task(fs, 'stat', '/path/to/file-2')\n      .task(fs, 'stat', '/path/to/file-3')\n      .on('stat', function(err, path, stat) {\n        console.log('%s is a %s', stat.isDirectory() ? 'directory' : 'file');\n      })\n      .on('done', function() {\n        console.log('finished!');\n      });\n\n### done\n\nEmitted when all tasks are complete.\n\n### error\n\nEmitted when any error occurs during the running of a `task()`. If this event is not handled an error will be thrown.\n\n### progress\n\nEmitted after a task has been completed.\n\n**Example:**\n\n    te.on('progress', function(status) {\n      console.log(status);\n    });\n    \n**Output:**\n\n    {\n      remaining: 4,\n      total: 8,\n      task: 'foo'\n    }\n\n\n","readmeFilename":"README.md","users":{"sharper":true,"freebird":true}}