如何从一个string创build一个subprocess

在浏览器中,我们可以从一个javascriptstring创build工作人员,如下所示:

var blob = new Blob([sourceString]); var url = window.URL.createObjectURL(blob); var worker = new Worker(url); 

有没有办法做到这一点与节点的subprocess ? 我有一个JavaScript文件,我想要创builddynamic编码的工作人员。

源string是在运行时dynamic创build的。

我发现最接近的答案是这一个 ,但它需要一个单独的文件。

如果我理解你的话,我创造了一个模块 ,就是那个。

它并不是打算从string中创build工作者,而是从实际的function创build工作者,因为实际的function代码必须被传递给思想的信息,他们在工作者内部被重新构build(思想eval())。

这是完成的想法代码:

 var source = fn.toString(); 

…所以,拥有该string原型也有一个.toString()方法,传递函数作为string必须工作(实际上工作,我只是testing它)。

它可能不是你想要的:如果你需要传入和传出工作人员的消息,这个模块不适合你。 但是你可以看到代码并修改它以适应你的需要。

另一方面,如果你只想在后台执行一些函数并得到结果,那么比处理工人pipe道更简单,因为你可以将parameter passing给函数,并得到结果就像一个简单的函数调用一样。

例:

 // Reauires funwork (`npm install --save funwork`) var funwork = require("funwork"); var workerfn = funwork(function_src_string); // or actual function. 

它的缺点是函数必须通过eval()来评估,但是在你的情况下(有一个string源),我认为这是必须的。

编辑:这是一个修改版本的funwork来处理你想要的东西,正如我们在评论中所讨论的那样:

 var Worker = require('webworker-threads').Worker; var Deasync = require('deasync'); function strWorker(fn){ var source = fn.toString(); return function() { var done = false; var args = Array.prototype.slice.call(arguments); var error; // Create worker://{{{ var worker = new Worker(function(){ var fn; var me = this; // Wait for function source and arguments: me.onmessage = function(event) { switch (event.data.oper) { case "src": // "Compile" function thougt source evaluation. try { eval ("fn = " + event.data.msg + ";"); postMessage(['ready']); } catch (e) { postMessage(['error', "Error trying to evaluate function source"]); }; break; case "args": // Call the function with given arguments and reset the rest of worker stuff. try { // Reset worker (inside) event handler: delete me.onmessage; // Notify that worker is ready: postMessage(["ok"]); // Start function execution: fn.apply(me, event.data.msg); } catch (e) { postMessage(['error', e]); }; break; }; }; });//}}} // Event handling://{{{ worker.onmessage = function(event) { switch (event.data[0]) { case 'error': worker.postMessage({oper: "end"}); done = true; error = event.data[1]; break; case 'ready': worker.postMessage({oper: "args", msg: args}); break; case 'ok': done = true; break; }; };//}}} // Send function source to worker: worker.postMessage({oper: "src", msg: source}); // Wait (without blocking) until worker executed passed function: Deasync.loopWhile(function(){return !done;}); if (error) throw error; // Reset worker (outside) event handler: delete worker.onmessage; return worker; }; }; module.exports = strWorker; 

我保留了将parameter passing给函数的能力,因为它已经被实现了,如果你不需要传递任何东西,你可以简单的使用它。

使用方法与唯一的区别是生成的函数返回正在运行的工作人员而不是函数返回值。

在函数(传入string)执行和工作者返回之前,使用的事件处理程序(工作者内部和外部)分别被删除,以避免任何副作用,并且传入函数的执行上下文(“this”)也是设置为实际的工人“父母”function。 。

如果您希望单个文件js启动不同的进程,创build群集可能是一个解决scheme。 这是一个相当不错的教程: 教程

基本节点来与本地集群模块

 var cluster = require('cluster'); 

您可以通过cluster.isMaster来判断进程是主进程还是工作进程。 如果进程是主进程,则可以通过执行cluster.fork()

 if (cluster.isMaster) { for (var i = 0; i < numCPUs; i++) { cluster.fork(); } } else { http.createServer(function(req, res) { res.writeHead(200); res.end('process ' + process.pid + ' says hello!'); }).listen(8000); } 

希望这可以帮助。

至于subprocess,你可以通过child_process.fork(modulePath [,args] [,options])来运行其他模块并传入参数。 模块可以根据参数做不同的事情,所以它是dynamic的…似乎你只是希望基于input的dynamic行为和child_process可以做到这一点,如果你可以把代码放在不同的文件。 如果只能有一个,请尝试群集解决scheme。