如何从字符串创建子进程

Tho*_*s W 10 javascript node.js

在浏览器中,我们可以从javascript字符串创建worker,如下所示:

var blob = new Blob([sourceString]);
var url = window.URL.createObjectURL(blob);
var worker = new Worker(url);
Run Code Online (Sandbox Code Playgroud)

有什么方法可以使用node的子进程执行此操作吗?我有一个JavaScript文件,我想创建动态编码的工作程序.

源字符串是在运行时动态创建的.

我找到的最接近的答案是这个,但它需要一个单独的文件.

bit*_*fet 10

如果我理解你的话,我创建了一个昨天做的模块.

它不打算从字符串创建worker,而是从实际函数创建,因为实际的函数代码必须通过思想消息传递,它们被字符串化以在worker中重建(思想eval()).

这是完成以为代码:

var source = fn.toString();
Run Code Online (Sandbox Code Playgroud)

...所以,拥有该字符串原型也有一个.toString()方法,将函数作为字符串传递也必须工作(事实上工作.我只是测试它).

它可能不是您想要的:如果您需要向工作人员传递和传递消息,则此模块不适合您.但是你可以看到代码并修改它以满足你的需要.

另一方面,如果你只想在后台执行某些函数并获得结果,那么它比处理worker plumbings要简单得多,因为你可以将函数传入函数并获得结果,就像一个简单的函数调用一样.

例:

// Reauires funwork (`npm install --save funwork`)

var funwork = require("funwork");
var workerfn = funwork(function_src_string); // or actual function.
Run Code Online (Sandbox Code Playgroud)

它的缺点是必须对函数进行评估,eval()但在你的情况下,(有一个字符串源代码)我觉得这绝对是必须的.

编辑:这是一个修改后的乐趣版本,可以在评论中讨论您想要的内容:

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;
Run Code Online (Sandbox Code Playgroud)

我保留了将参数传递给函数的能力,因为它已经实现了,如果你不需要传递任何东西,你就可以不使用它.

用法与生成的函数返回正在运行的worker而不是函数返回值的唯一区别相同.

在函数(作为字符串传递)执行和工作程序返回之前分别删除使用的事件处理程序(worker内部和外部)以避免任何副作用,并且传入函数的执行上下文("this")也是设置为实际的工作人员"父"功能..