在浏览器中,我们可以使用javascript字符串创建worker,如下所示:
$(".left-col-content > .content").append(() => {
return "left-col<br>".repeat(350);
});
$(".right-col-content > .content").append(() => {
return "right-col<br>".repeat(350);
});
$(".terminal-row > .content").append(() => {
return "terminal<br>".repeat(350);
});
$(".body-col-content > .content").append(() => {
return "content<br>".repeat(350);
});
$(".body-col-header > .content").append(() => {
left_btn = $("<button>Toggle Left</button>").click(() => {
$(".left-col").toggle();
$(".body-col").toggleClass("left-hidden");
});
right_btn = $("<button>Toggle Right</button>").click(() => {
$(".right-col").toggle();
$(".body-col").toggleClass("right-hidden");
});
terminal_btn = $("<button>Toggle Terminal</button>").click(() => {
$(".terminal-row").toggle();
$(".main-row").toggleClass("terminal-hidden");
});
buttons = $("<div></div>")
.append(left_btn)
.append(right_btn)
.append(terminal_btn);
return buttons;
});
有没有办法用节点的child process做到这一点?我有一个JavaScript文件,我想创建动态编码的工作程序。
源字符串是在运行时动态创建的。
我找到的最接近的答案是this one,但它需要一个单独的文件。
答案 0 :(得分:10)
如果我理解正确的话,我创建了a module,它就是昨天做的。
它不打算从字符串创建worker,而是从实际函数创建,因为实际的函数代码必须通过思想消息传递,它们被字符串化以在工作者中重建(思考eval())。
这是在代码中完成的:
var source = fn.toString();
...所以,拥有该字符串原型也有一个.toString()
方法,将函数作为字符串传递也必须工作(事实上是有效的。我只是测试了它。)
可能不是您想要的:如果您需要向工作人员传递和传递消息,则此模块不适合您。但是你可以看到the code并修改它以满足你的需要。
另一方面,如果你只想在后台执行某些函数并获得结果,那么它比处理工作线程更简单,因为你可以将函数传入函数并获得结果就像一个简单的函数调用
示例:强>
// Reauires funwork (`npm install --save funwork`)
var funwork = require("funwork");
var workerfn = funwork(function_src_string); // or actual function.
它的缺点是必须通过eval()
来评估函数,但在你的情况下,(有一个字符串源代码)我觉得这绝对是必须的。
编辑:以下是 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;
我保留了将参数传递给函数的能力,因为它已经实现了,如果你不需要传递任何东西,你就可以不使用它。
用法与生成的函数返回正在运行的worker而不是函数返回值的唯一区别相同。
使用的事件处理程序(worker内部和外部)分别在函数(作为字符串传入)执行和worker返回之前被删除,以避免任何副作用和执行上下文(&#34; this&#34;)传入函数的设置也设置为实际的工作者&#34; parent&#34;功能。
答案 1 :(得分:2)
如果您希望单个文件js启动不同的进程,则创建群集可能是一种解决方案。这是一个非常好的教程:Tutorial
基本上节点带有本机群集模块
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);
}
希望这有帮助。
对于子进程,您可以 child_process.fork(modulePath [,args] [,options])来运行其他模块并传入参数。模块可以根据参数执行不同的操作,因此它是动态的...似乎您只需要基于输入的动态行为,如果您可以将代码放在不同的文件中,则child_process可以执行此操作。如果只能有一个,请尝试使用群集解决方案。