workerpool
Advanced tools
Comparing version 0.2.0 to 1.0.0
@@ -7,4 +7,4 @@ /** | ||
* | ||
* @version 0.2.0 | ||
* @date 2014-05-14 | ||
* @version 1.0.0 | ||
* @date 2014-05-29 | ||
* | ||
@@ -167,11 +167,16 @@ * @license | ||
/** | ||
* Offload execution of a function to a worker. | ||
* Execute a function on a worker. | ||
* | ||
* Example usage: | ||
* | ||
* var pool = new Pool() | ||
* | ||
* // call a function available on the worker | ||
* pool.exec('fibonacci', [6]) | ||
* | ||
* // offload a function | ||
* function add(a, b) { | ||
* return a + b | ||
* }; | ||
* var pool = new Pool() | ||
* pool.run(add, [2, 4]) | ||
* pool.exec(add, [2, 4]) | ||
* .then(function (result) { | ||
@@ -184,44 +189,39 @@ * console.log(result); // outputs 6 | ||
* | ||
* @param {Function} fn The function to be executed. The function must be | ||
* serializable and must not depend on external | ||
* variables. | ||
* @param {Array} [args] Arguments applied when calling the function | ||
* @param {String | Function} method Function name or function. | ||
* If `method` is a string, the corresponding | ||
* method on the worker will be executed | ||
* If `method` is a Function, the function | ||
* will be stringified and executed via the | ||
* workers built-in function `run(fn, args)`. | ||
* @param {Array} [params] Function arguments applied when calling the function | ||
* @return {Promise.<*, Error>} result | ||
*/ | ||
Pool.prototype.run = function (fn, args) { | ||
Pool.prototype.exec = function (method, params) { | ||
// validate type of arguments | ||
if (typeof fn !== 'function') { | ||
throw new TypeError('Function expected as argument "fn"'); | ||
if (params && !Array.isArray(params)) { | ||
throw new TypeError('Array expected as argument "params"'); | ||
} | ||
if (args && !Array.isArray(args)) { | ||
throw new TypeError('Array expected as argument "args"'); | ||
} | ||
// send stringified function and function arguments to worker | ||
return this.exec('run', [String(fn), args]); | ||
}; | ||
if (typeof method === 'string') { | ||
var resolver = Promise.defer(); | ||
/** | ||
* Execute a function on a worker | ||
* | ||
* @param {String} method Function name. The function must be present on | ||
* the worker | ||
* @param {Array} [params] Function arguments applied when calling the function | ||
* @return {Promise.<*, Error>} result | ||
*/ | ||
Pool.prototype.exec = function (method, params) { | ||
var me = this; | ||
var resolver = Promise.defer(); | ||
// add a new task to the queue | ||
this.tasks.push({ | ||
method: method, | ||
params: params, | ||
resolver: resolver | ||
}); | ||
// add a new task to the queue | ||
this.tasks.push({ | ||
method: method, | ||
params: params, | ||
resolver: resolver | ||
}); | ||
// trigger task execution | ||
this._next(); | ||
// trigger task execution | ||
this._next(); | ||
return resolver.promise; | ||
return resolver.promise; | ||
} | ||
else if (typeof method === 'function') { | ||
// send stringified function and function arguments to worker | ||
return this.exec('run', [String(method), params]); | ||
} | ||
else { | ||
throw new TypeError('Function or string expected as argument "method"'); | ||
} | ||
}; | ||
@@ -228,0 +228,0 @@ |
@@ -7,4 +7,4 @@ /** | ||
* | ||
* @version 0.2.0 | ||
* @date 2014-05-14 | ||
* @version 1.0.0 | ||
* @date 2014-05-29 | ||
* | ||
@@ -26,3 +26,3 @@ * @license | ||
*/ | ||
!function(r,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("os"),require("child_process")):"function"==typeof define&&define.amd?define(["os","child_process"],e):"object"==typeof exports?exports.workerpool=e(require("os"),require("child_process")):r.workerpool=e(r.os,r.child_process)}(this,function(__WEBPACK_EXTERNAL_MODULE_6__,__WEBPACK_EXTERNAL_MODULE_8__){return function(r){function e(o){if(t[o])return t[o].exports;var n=t[o]={exports:{},id:o,loaded:!1};return r[o].call(n.exports,n,n.exports,e),n.loaded=!0,n.exports}var t={};return e.m=r,e.c=t,e.p="",e(0)}([function(r,e,t){e.pool=function(r){var e=t(1);return new e(r)},e.worker=function o(r){var e=t(2);if("browser"==e){var n=new Blob([t(3)],{type:"text/javascript"}),i=window.URL.createObjectURL(n);importScripts(i)}else var o=t(4);o.add(r)},e.Promise=t(5)},function(r,e,t){function o(r,e){if("string"==typeof r?this.script=r||null:(this.script=null,e=r),e&&"maxWorkers"in e){if(!n(e.maxWorkers)||!i(e.maxWorkers)||e.maxWorkers<1)throw new TypeError("Option maxWorkers must be a positive integer number");this.maxWorkers=e.maxWorkers}else{var o=t(2),s="browser"==o?4:t(6).cpus().length;this.maxWorkers=Math.max(s-1,1)}this.workers=[],this.tasks=[]}function n(r){return"number"==typeof r}function i(r){return Math.round(r)==r}var s=t(5),c=t(7);o.prototype.run=function(r,e){if("function"!=typeof r)throw new TypeError('Function expected as argument "fn"');if(e&&!Array.isArray(e))throw new TypeError('Array expected as argument "args"');return this.exec("run",[String(r),e])},o.prototype.exec=function(r,e){var t=s.defer();return this.tasks.push({method:r,params:e,resolver:t}),this._next(),t.promise},o.prototype.proxy=function(){var r=this;return this.exec("methods").then(function(e){var t={};return e.forEach(function(e){t[e]=function(){return r.exec(e,Array.prototype.slice.call(arguments))}}),t})},o.prototype._next=function(){if(this.tasks.length>0){var r=this._getWorker();if(r){var e=this,t=this.tasks.shift();t.resolver.promise.pending&&r.exec(t.method,t.params,t.resolver).then(function(){e._next()}).catch(function(){r.terminated&&e._removeWorker(r),e._next()})}}},o.prototype._getWorker=function(){for(var r=0,e=this.workers.length;e>r;r++){var t=this.workers[r];if(!t.busy())return t}return this.workers.length<this.maxWorkers?(t=new c(this.script),this.workers.push(t),t):null},o.prototype._removeWorker=function(r){r.terminate();var e=this.workers.indexOf(r);-1!=e&&this.workers.splice(e,1)},o.prototype.clear=function(r){this.workers.forEach(function(e){e.terminate(r)}),this.workers=[]},r.exports=o},function(r){r.exports="undefined"!=typeof window?"browser":"node"},function(r){r.exports='function isPromise(e){return e&&"function"==typeof e.then&&"function"==typeof e.catch}var worker={};if("undefined"!=typeof self&&"function"==typeof postMessage&&"function"==typeof addEventListener)worker.on=function(e,r){addEventListener(e,function(e){r(e.data)})},worker.send=function(e){postMessage(e)};else{if("undefined"==typeof process)throw new Error("Script must be executed as a worker");worker.on=process.on.bind(process),worker.send=process.send.bind(process)}worker.methods={},worker.methods.run=function run(fn,args){var f=eval("("+fn+")");return f.apply(f,args)},worker.methods.methods=function(){return Object.keys(worker.methods)},worker.on("message",function(e){try{var r=worker.methods[e.method];if(!r)throw new Error(\'Unknown method "\'+e.method+\'"\');var o=r.apply(r,e.params);isPromise(o)?o.then(function(r){worker.send({id:e.id,result:r,error:null})}).catch(function(r){worker.send({id:e.id,result:null,error:r.toString()})}):worker.send({id:e.id,result:o,error:null})}catch(n){worker.send({id:e.id,result:null,error:n.toString()})}}),worker.register=function(e){if(e)for(var r in e)e.hasOwnProperty(r)&&(worker.methods[r]=e[r])},"undefined"!=typeof exports&&(exports.add=worker.register);'},function(module,exports,__webpack_require__){function isPromise(r){return r&&"function"==typeof r.then&&"function"==typeof r.catch}var worker={};if("undefined"!=typeof self&&"function"==typeof postMessage&&"function"==typeof addEventListener)worker.on=function(r,e){addEventListener(r,function(r){e(r.data)})},worker.send=function(r){postMessage(r)};else{if("undefined"==typeof process)throw new Error("Script must be executed as a worker");worker.on=process.on.bind(process),worker.send=process.send.bind(process)}worker.methods={},worker.methods.run=function run(fn,args){var f=eval("("+fn+")");return f.apply(f,args)},worker.methods.methods=function(){return Object.keys(worker.methods)},worker.on("message",function(r){try{var e=worker.methods[r.method];if(!e)throw new Error('Unknown method "'+r.method+'"');var t=e.apply(e,r.params);isPromise(t)?t.then(function(e){worker.send({id:r.id,result:e,error:null})}).catch(function(e){worker.send({id:r.id,result:null,error:e.toString()})}):worker.send({id:r.id,result:t,error:null})}catch(o){worker.send({id:r.id,result:null,error:o.toString()})}}),worker.register=function(r){if(r)for(var e in r)r.hasOwnProperty(e)&&(worker.methods[e]=r[e])},exports.add=worker.register},function(r){"use strict";function e(r,i){var s=this;if(!(this instanceof e))throw new SyntaxError("Constructor must be called with the new operator");if("function"!=typeof r)throw new SyntaxError("Function parameter handler(resolve, reject) missing");var c=[],u=[];this.resolved=!1,this.rejected=!1,this.pending=!0;var a=function(r,e){c.push(r),u.push(e)};this.then=function(r,o){return new e(function(e,n){var i=r?t(r,e,n):e,s=o?t(o,e,n):n;a(i,s)},s)};var f=function(r){return s.resolved=!0,s.rejected=!1,s.pending=!1,c.forEach(function(e){e(r)}),a=function(e){e(r)},f=p=function(){throw new Error("Promise is already resolved")},s},p=function(r){return s.resolved=!1,s.rejected=!0,s.pending=!1,u.forEach(function(e){e(r)}),a=function(e,t){t(r)},f=p=function(){throw new Error("Promise is already resolved")},s};this.cancel=function(){return i?i.cancel():p(new o),s},this.timeout=function(r){if(i)i.timeout(r);else{var e=setTimeout(function(){p(new n("Promise timed out after "+r+" ms"))},r);s.always(function(){clearTimeout(e)})}return s},r(function(r){f(r)},function(r){p(r)})}function t(r,e,t){return function(o){try{var n=r(o);n&&"function"==typeof n.then&&"function"==typeof n["catch"]?n.then(e,t):e(n)}catch(i){t(i)}}}function o(r){this.message=r||"promise cancelled",this.stack=(new Error).stack}function n(r){this.message=r||"timeout exceeded",this.stack=(new Error).stack}e.prototype["catch"]=function(r){return this.then(null,r)},e.prototype.always=function(r){return this.then(r,r)},e.all=function(r){return new e(function(e,t){var o=r.length,n=[];o?r.forEach(function(r,i){r.then(function(r){n[i]=r,o--,0==o&&e(n)},function(r){o=0,t(r)})}):e(n)})},e.defer=function(){var r={};return r.promise=new e(function(e,t){r.resolve=e,r.reject=t}),r},o.prototype=new Error,o.prototype.constructor=Error,o.prototype.name="CancellationError",e.CancellationError=o,n.prototype=new Error,n.prototype.constructor=Error,n.prototype.name="TimeoutError",e.TimeoutError=n,r.exports=e},function(r){r.exports=require("os")},function(r,e,t){function o(){if("browser"==s){if("undefined"==typeof Blob)throw new Error("Blob not supported by the browser");if(!window.URL||"function"!=typeof window.URL.createObjectURL)throw new Error("URL.createObjectURL not supported by the browser");var r=new Blob([t(3)],{type:"text/javascript"});return window.URL.createObjectURL(r)}return __dirname+"/worker.js"}function n(r){function e(r){n.terminated=!0;for(var e in n.processing)n.processing.hasOwnProperty(e)&&n.processing[e].resolver.reject(r);n.processing={}}if(this.script=r||o(),"browser"==s){if("function"!=typeof Worker)throw new Error("Web workers not supported by the browser");this.worker=new Worker(this.script),this.worker.on=function(r,e){this.addEventListener(r,function(r){e(r.data)})},this.worker.send=function(r){this.postMessage(r)}}else this.worker=t(8).fork(this.script);var n=this;this.worker.on("message",function(r){var e=r.id,t=n.processing[e];t&&(delete n.processing[e],n.terminating&&n.terminate(),r.error?t.resolver.reject(r.error):t.resolver.resolve(r.result))}),this.worker.on("error",e),this.worker.on("exit",function(){var r=new Error("Worker terminated unexpectedly");e(r)}),this.processing={},this.terminating=!1,this.terminated=!1,this.lastId=0}var i=t(5),s=t(2);n.prototype.methods=function(){return this.exec("methods")},n.prototype.exec=function(r,e,t){t||(t=i.defer());var o=++this.lastId;this.processing[o]={id:o,resolver:t};var n={id:o,method:r,params:e};this.terminated?t.reject(new Error("Worker is terminated")):this.worker.send(n);var s=this;return t.promise.catch(function(r){(r instanceof i.CancellationError||r instanceof i.TimeoutError)&&(delete s.processing[o],s.terminate(!0))}),t.promise},n.prototype.busy=function(){return Object.keys(this.processing).length>0},n.prototype.terminate=function(r){if(r){for(var e in this.processing)this.processing.hasOwnProperty(e)&&this.processing[e].resolver.reject(new Error("Worker terminated"));this.processing={}}if(this.busy())this.terminating=!0;else{if(this.worker){if("function"==typeof this.worker.kill)this.worker.kill();else{if("function"!=typeof this.worker.terminate)throw new Error("Failed to terminate worker");this.worker.terminate()}this.worker=null}this.terminating=!1,this.terminated=!0}},r.exports=n},function(r){r.exports=require("child_process")}])}); | ||
!function(r,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("os"),require("child_process")):"function"==typeof define&&define.amd?define(["os","child_process"],e):"object"==typeof exports?exports.workerpool=e(require("os"),require("child_process")):r.workerpool=e(r.os,r.child_process)}(this,function(__WEBPACK_EXTERNAL_MODULE_6__,__WEBPACK_EXTERNAL_MODULE_8__){return function(r){function e(o){if(t[o])return t[o].exports;var n=t[o]={exports:{},id:o,loaded:!1};return r[o].call(n.exports,n,n.exports,e),n.loaded=!0,n.exports}var t={};return e.m=r,e.c=t,e.p="",e(0)}([function(r,e,t){e.pool=function(r){var e=t(1);return new e(r)},e.worker=function o(r){var e=t(2);if("browser"==e){var n=new Blob([t(3)],{type:"text/javascript"}),i=window.URL.createObjectURL(n);importScripts(i)}else var o=t(4);o.add(r)},e.Promise=t(5)},function(r,e,t){function o(r,e){if("string"==typeof r?this.script=r||null:(this.script=null,e=r),e&&"maxWorkers"in e){if(!n(e.maxWorkers)||!i(e.maxWorkers)||e.maxWorkers<1)throw new TypeError("Option maxWorkers must be a positive integer number");this.maxWorkers=e.maxWorkers}else{var o=t(2),s="browser"==o?4:t(6).cpus().length;this.maxWorkers=Math.max(s-1,1)}this.workers=[],this.tasks=[]}function n(r){return"number"==typeof r}function i(r){return Math.round(r)==r}var s=t(5),c=t(7);o.prototype.exec=function(r,e){if(e&&!Array.isArray(e))throw new TypeError('Array expected as argument "params"');if("string"==typeof r){var t=s.defer();return this.tasks.push({method:r,params:e,resolver:t}),this._next(),t.promise}if("function"==typeof r)return this.exec("run",[String(r),e]);throw new TypeError('Function or string expected as argument "method"')},o.prototype.proxy=function(){var r=this;return this.exec("methods").then(function(e){var t={};return e.forEach(function(e){t[e]=function(){return r.exec(e,Array.prototype.slice.call(arguments))}}),t})},o.prototype._next=function(){if(this.tasks.length>0){var r=this._getWorker();if(r){var e=this,t=this.tasks.shift();t.resolver.promise.pending&&r.exec(t.method,t.params,t.resolver).then(function(){e._next()}).catch(function(){r.terminated&&e._removeWorker(r),e._next()})}}},o.prototype._getWorker=function(){for(var r=0,e=this.workers.length;e>r;r++){var t=this.workers[r];if(!t.busy())return t}return this.workers.length<this.maxWorkers?(t=new c(this.script),this.workers.push(t),t):null},o.prototype._removeWorker=function(r){r.terminate();var e=this.workers.indexOf(r);-1!=e&&this.workers.splice(e,1)},o.prototype.clear=function(r){this.workers.forEach(function(e){e.terminate(r)}),this.workers=[]},r.exports=o},function(r){r.exports="undefined"!=typeof window?"browser":"node"},function(r){r.exports='function isPromise(e){return e&&"function"==typeof e.then&&"function"==typeof e.catch}var worker={};if("undefined"!=typeof self&&"function"==typeof postMessage&&"function"==typeof addEventListener)worker.on=function(e,r){addEventListener(e,function(e){r(e.data)})},worker.send=function(e){postMessage(e)};else{if("undefined"==typeof process)throw new Error("Script must be executed as a worker");worker.on=process.on.bind(process),worker.send=process.send.bind(process)}worker.methods={},worker.methods.run=function run(fn,args){var f=eval("("+fn+")");return f.apply(f,args)},worker.methods.methods=function(){return Object.keys(worker.methods)},worker.on("message",function(e){try{var r=worker.methods[e.method];if(!r)throw new Error(\'Unknown method "\'+e.method+\'"\');var o=r.apply(r,e.params);isPromise(o)?o.then(function(r){worker.send({id:e.id,result:r,error:null})}).catch(function(r){worker.send({id:e.id,result:null,error:r.toString()})}):worker.send({id:e.id,result:o,error:null})}catch(n){worker.send({id:e.id,result:null,error:n.toString()})}}),worker.register=function(e){if(e)for(var r in e)e.hasOwnProperty(r)&&(worker.methods[r]=e[r])},"undefined"!=typeof exports&&(exports.add=worker.register);'},function(module,exports,__webpack_require__){function isPromise(r){return r&&"function"==typeof r.then&&"function"==typeof r.catch}var worker={};if("undefined"!=typeof self&&"function"==typeof postMessage&&"function"==typeof addEventListener)worker.on=function(r,e){addEventListener(r,function(r){e(r.data)})},worker.send=function(r){postMessage(r)};else{if("undefined"==typeof process)throw new Error("Script must be executed as a worker");worker.on=process.on.bind(process),worker.send=process.send.bind(process)}worker.methods={},worker.methods.run=function run(fn,args){var f=eval("("+fn+")");return f.apply(f,args)},worker.methods.methods=function(){return Object.keys(worker.methods)},worker.on("message",function(r){try{var e=worker.methods[r.method];if(!e)throw new Error('Unknown method "'+r.method+'"');var t=e.apply(e,r.params);isPromise(t)?t.then(function(e){worker.send({id:r.id,result:e,error:null})}).catch(function(e){worker.send({id:r.id,result:null,error:e.toString()})}):worker.send({id:r.id,result:t,error:null})}catch(o){worker.send({id:r.id,result:null,error:o.toString()})}}),worker.register=function(r){if(r)for(var e in r)r.hasOwnProperty(e)&&(worker.methods[e]=r[e])},exports.add=worker.register},function(r){"use strict";function e(r,i){var s=this;if(!(this instanceof e))throw new SyntaxError("Constructor must be called with the new operator");if("function"!=typeof r)throw new SyntaxError("Function parameter handler(resolve, reject) missing");var c=[],u=[];this.resolved=!1,this.rejected=!1,this.pending=!0;var a=function(r,e){c.push(r),u.push(e)};this.then=function(r,o){return new e(function(e,n){var i=r?t(r,e,n):e,s=o?t(o,e,n):n;a(i,s)},s)};var f=function(r){return s.resolved=!0,s.rejected=!1,s.pending=!1,c.forEach(function(e){e(r)}),a=function(e){e(r)},f=p=function(){throw new Error("Promise is already resolved")},s},p=function(r){return s.resolved=!1,s.rejected=!0,s.pending=!1,u.forEach(function(e){e(r)}),a=function(e,t){t(r)},f=p=function(){throw new Error("Promise is already resolved")},s};this.cancel=function(){return i?i.cancel():p(new o),s},this.timeout=function(r){if(i)i.timeout(r);else{var e=setTimeout(function(){p(new n("Promise timed out after "+r+" ms"))},r);s.always(function(){clearTimeout(e)})}return s},r(function(r){f(r)},function(r){p(r)})}function t(r,e,t){return function(o){try{var n=r(o);n&&"function"==typeof n.then&&"function"==typeof n["catch"]?n.then(e,t):e(n)}catch(i){t(i)}}}function o(r){this.message=r||"promise cancelled",this.stack=(new Error).stack}function n(r){this.message=r||"timeout exceeded",this.stack=(new Error).stack}e.prototype["catch"]=function(r){return this.then(null,r)},e.prototype.always=function(r){return this.then(r,r)},e.all=function(r){return new e(function(e,t){var o=r.length,n=[];o?r.forEach(function(r,i){r.then(function(r){n[i]=r,o--,0==o&&e(n)},function(r){o=0,t(r)})}):e(n)})},e.defer=function(){var r={};return r.promise=new e(function(e,t){r.resolve=e,r.reject=t}),r},o.prototype=new Error,o.prototype.constructor=Error,o.prototype.name="CancellationError",e.CancellationError=o,n.prototype=new Error,n.prototype.constructor=Error,n.prototype.name="TimeoutError",e.TimeoutError=n,r.exports=e},function(r){r.exports=require("os")},function(r,e,t){function o(){if("browser"==s){if("undefined"==typeof Blob)throw new Error("Blob not supported by the browser");if(!window.URL||"function"!=typeof window.URL.createObjectURL)throw new Error("URL.createObjectURL not supported by the browser");var r=new Blob([t(3)],{type:"text/javascript"});return window.URL.createObjectURL(r)}return __dirname+"/worker.js"}function n(r){function e(r){n.terminated=!0;for(var e in n.processing)n.processing.hasOwnProperty(e)&&n.processing[e].resolver.reject(r);n.processing={}}if(this.script=r||o(),"browser"==s){if("function"!=typeof Worker)throw new Error("Web workers not supported by the browser");this.worker=new Worker(this.script),this.worker.on=function(r,e){this.addEventListener(r,function(r){e(r.data)})},this.worker.send=function(r){this.postMessage(r)}}else this.worker=t(8).fork(this.script);var n=this;this.worker.on("message",function(r){var e=r.id,t=n.processing[e];t&&(delete n.processing[e],n.terminating&&n.terminate(),r.error?t.resolver.reject(r.error):t.resolver.resolve(r.result))}),this.worker.on("error",e),this.worker.on("exit",function(){var r=new Error("Worker terminated unexpectedly");e(r)}),this.processing={},this.terminating=!1,this.terminated=!1,this.lastId=0}var i=t(5),s=t(2);n.prototype.methods=function(){return this.exec("methods")},n.prototype.exec=function(r,e,t){t||(t=i.defer());var o=++this.lastId;this.processing[o]={id:o,resolver:t};var n={id:o,method:r,params:e};this.terminated?t.reject(new Error("Worker is terminated")):this.worker.send(n);var s=this;return t.promise.catch(function(r){(r instanceof i.CancellationError||r instanceof i.TimeoutError)&&(delete s.processing[o],s.terminate(!0))}),t.promise},n.prototype.busy=function(){return Object.keys(this.processing).length>0},n.prototype.terminate=function(r){if(r){for(var e in this.processing)this.processing.hasOwnProperty(e)&&this.processing[e].resolver.reject(new Error("Worker terminated"));this.processing={}}if(this.busy())this.terminating=!0;else{if(this.worker){if("function"==typeof this.worker.kill)this.worker.kill();else{if("function"!=typeof this.worker.terminate)throw new Error("Failed to terminate worker");this.worker.terminate()}this.worker=null}this.terminating=!1,this.terminated=!0}},r.exports=n},function(r){r.exports=require("child_process")}])}); | ||
//# sourceMappingURL=workerpool.map |
@@ -5,2 +5,7 @@ # workerpool history | ||
## 2014-05-29, version 1.0.0 | ||
- Merged function `Pool.run` into `Pool.exec`, simplifying the API. | ||
## 2014-05-14, version 0.2.0 | ||
@@ -7,0 +12,0 @@ |
@@ -37,11 +37,16 @@ var Promise = require('./Promise'), | ||
/** | ||
* Offload execution of a function to a worker. | ||
* Execute a function on a worker. | ||
* | ||
* Example usage: | ||
* | ||
* var pool = new Pool() | ||
* | ||
* // call a function available on the worker | ||
* pool.exec('fibonacci', [6]) | ||
* | ||
* // offload a function | ||
* function add(a, b) { | ||
* return a + b | ||
* }; | ||
* var pool = new Pool() | ||
* pool.run(add, [2, 4]) | ||
* pool.exec(add, [2, 4]) | ||
* .then(function (result) { | ||
@@ -54,44 +59,39 @@ * console.log(result); // outputs 6 | ||
* | ||
* @param {Function} fn The function to be executed. The function must be | ||
* serializable and must not depend on external | ||
* variables. | ||
* @param {Array} [args] Arguments applied when calling the function | ||
* @param {String | Function} method Function name or function. | ||
* If `method` is a string, the corresponding | ||
* method on the worker will be executed | ||
* If `method` is a Function, the function | ||
* will be stringified and executed via the | ||
* workers built-in function `run(fn, args)`. | ||
* @param {Array} [params] Function arguments applied when calling the function | ||
* @return {Promise.<*, Error>} result | ||
*/ | ||
Pool.prototype.run = function (fn, args) { | ||
Pool.prototype.exec = function (method, params) { | ||
// validate type of arguments | ||
if (typeof fn !== 'function') { | ||
throw new TypeError('Function expected as argument "fn"'); | ||
if (params && !Array.isArray(params)) { | ||
throw new TypeError('Array expected as argument "params"'); | ||
} | ||
if (args && !Array.isArray(args)) { | ||
throw new TypeError('Array expected as argument "args"'); | ||
} | ||
// send stringified function and function arguments to worker | ||
return this.exec('run', [String(fn), args]); | ||
}; | ||
if (typeof method === 'string') { | ||
var resolver = Promise.defer(); | ||
/** | ||
* Execute a function on a worker | ||
* | ||
* @param {String} method Function name. The function must be present on | ||
* the worker | ||
* @param {Array} [params] Function arguments applied when calling the function | ||
* @return {Promise.<*, Error>} result | ||
*/ | ||
Pool.prototype.exec = function (method, params) { | ||
var me = this; | ||
var resolver = Promise.defer(); | ||
// add a new task to the queue | ||
this.tasks.push({ | ||
method: method, | ||
params: params, | ||
resolver: resolver | ||
}); | ||
// add a new task to the queue | ||
this.tasks.push({ | ||
method: method, | ||
params: params, | ||
resolver: resolver | ||
}); | ||
// trigger task execution | ||
this._next(); | ||
// trigger task execution | ||
this._next(); | ||
return resolver.promise; | ||
return resolver.promise; | ||
} | ||
else if (typeof method === 'function') { | ||
// send stringified function and function arguments to worker | ||
return this.exec('run', [String(method), params]); | ||
} | ||
else { | ||
throw new TypeError('Function or string expected as argument "method"'); | ||
} | ||
}; | ||
@@ -98,0 +98,0 @@ |
{ | ||
"name": "workerpool", | ||
"version": "0.2.0", | ||
"version": "1.0.0", | ||
"description": "Offload tasks to a pool of workers on node.js and in the browser", | ||
@@ -5,0 +5,0 @@ "homepage": "https://github.com/josdejong/workerpool", |
@@ -20,3 +20,3 @@ var assert = require('assert'), | ||
pool.run(add, [3, 4]) | ||
pool.exec(add, [3, 4]) | ||
.then(function (result) { | ||
@@ -46,4 +46,4 @@ assert.equal(result, 7); | ||
Promise.all([ | ||
pool.run(add, [3, 4]), | ||
pool.run(add, [2, 3]) | ||
pool.exec(add, [3, 4]), | ||
pool.exec(add, [2, 3]) | ||
]) | ||
@@ -71,4 +71,4 @@ .then(function (results) { | ||
var task1 = pool.run(add, [3, 4]); | ||
var task2 = pool.run(add, [2, 3]); | ||
var task1 = pool.exec(add, [3, 4]); | ||
var task2 = pool.exec(add, [2, 3]); | ||
@@ -78,4 +78,4 @@ assert.equal(pool.tasks.length, 0); | ||
var task3 = pool.run(add, [5, 7]); | ||
var task4 = pool.run(add, [1, 1]); | ||
var task3 = pool.exec(add, [5, 7]); | ||
var task4 = pool.exec(add, [1, 1]); | ||
@@ -143,3 +143,3 @@ assert.equal(pool.tasks.length, 2); | ||
pool.run(test) | ||
pool.exec(test) | ||
.catch(function (err) { | ||
@@ -160,3 +160,3 @@ assert.equal(err.toString(), 'TypeError: Test error'); | ||
var promise = pool.run(forever) | ||
var promise = pool.exec(forever) | ||
.then(function (result) { | ||
@@ -198,3 +198,3 @@ assert('promise should never resolve'); | ||
var p1 = pool.run(delayed) | ||
var p1 = pool.exec(delayed) | ||
.then(function (result) { | ||
@@ -213,3 +213,3 @@ assert.equal(result, 1); | ||
var p2 = pool.run(one); // will be queued | ||
var p2 = pool.exec(one); // will be queued | ||
assert.equal(pool.workers.length, 1); | ||
@@ -234,3 +234,3 @@ assert.equal(pool.tasks.length, 1); | ||
var promise = pool.run(forever) | ||
var promise = pool.exec(forever) | ||
.timeout(50) | ||
@@ -253,3 +253,3 @@ .then(function (result) { | ||
pool.run(add) | ||
pool.exec(add) | ||
.then(function () { | ||
@@ -264,3 +264,3 @@ assert('Promise should not be resolved'); | ||
// validate whether a new worker is spawned | ||
pool.run(add, [2,3]) | ||
pool.exec(add, [2,3]) | ||
.then(function (result) { | ||
@@ -309,7 +309,7 @@ assert.equal(result, 5); | ||
pool.run(add, [1, 2]); | ||
pool.run(add, [3, 4]); | ||
pool.run(add, [5, 6]); | ||
pool.run(add, [7, 8]); | ||
pool.run(add, [9, 0]); | ||
pool.exec(add, [1, 2]); | ||
pool.exec(add, [3, 4]); | ||
pool.exec(add, [5, 6]); | ||
pool.exec(add, [7, 8]); | ||
pool.exec(add, [9, 0]); | ||
@@ -347,3 +347,3 @@ assert.equal(pool.maxWorkers, 2); | ||
pool.run(test) | ||
pool.exec(test) | ||
.then(function (result) { | ||
@@ -373,3 +373,3 @@ assert.equal(result, 'ok'); | ||
pool.run(test) | ||
pool.exec(test) | ||
.then(function (result) { | ||
@@ -390,9 +390,11 @@ assert.equal(result, 'ok'); | ||
it('should throw an error in case of wrong type of arguments in function run', function () { | ||
it('should throw an error in case of wrong type of arguments in function exec', function () { | ||
var pool = new Pool(); | ||
assert.throws(function () {pool.run()}, TypeError); | ||
assert.throws(function () {pool.run('a string')}, TypeError); | ||
assert.throws(function () {pool.run(add, {})}, TypeError); | ||
assert.throws(function () {pool.exec()}, TypeError); | ||
assert.throws(function () {pool.exec(23)}, TypeError); | ||
assert.throws(function () {pool.exec(add, {})}, TypeError); | ||
assert.throws(function () {pool.exec(add, 2, 3)}, TypeError); | ||
assert.throws(function () {pool.exec(add, 'a string')}, TypeError); | ||
}); | ||
}); |
@@ -633,4 +633,43 @@ var assert = require('assert'), | ||
}); | ||
it('should resolve "all" when all of the promises are already resolved', function (done) { | ||
var foo = new Promise(function (resolve, reject) { | ||
resolve('foo'); | ||
}), | ||
bar = new Promise(function (resolve, reject) { | ||
resolve('bar'); | ||
}), | ||
baz = new Promise(function (resolve, reject) { | ||
resolve('baz'); | ||
}), | ||
qux = new Promise(function (resolve, reject) { | ||
resolve('qux'); | ||
}); | ||
Promise.all([foo, bar, baz, qux]) | ||
.then(function (results) { | ||
assert.ok(true, 'then'); | ||
assert.deepEqual(results, ['foo', 'bar', 'baz', 'qux']); | ||
done(); | ||
}) | ||
.catch(function (){ | ||
assert.ok(false, 'catch'); | ||
}); | ||
}); | ||
it('should resolve "all" when empty', function (done) { | ||
Promise.all([]) | ||
.then(function (results) { | ||
assert.ok(true, 'then'); | ||
assert.deepEqual(results, []); | ||
done(); | ||
}) | ||
.catch(function (){ | ||
assert.ok(false, 'catch'); | ||
}); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
3086
1
9
132897
1
0