Return 来自 Node.js 中多线程进程的值

Return value from multithreaded process in Node.js

我设计了一个函数 diversify() 来获取一些昂贵的函数 f() 和 运行 它在机器的所有内核上并行运行 运行 .我还对此进行了设置,以便如果 f() return 在一个核心上有一个值,则所有其他线程都会自动终止。代码如下:

let diversify = f => {
    // Split a function `f` into a thread for each core of the machine.
    // The first thread to finish will return its result and end all others.
    
    if ( cluster.isMaster ) {

        let children = []
        for ( let i = 0; i < os.cpus().length; i++) {
            children.push(cluster.fork())
        }

        cluster.on('message', (_, msg) => {

            if ( msg.cmd == 'stop' ) { children.forEach(child => {
                child.process.kill()
            })}

            return msg.out

        })

    } else {

        let out = f()
        process.send({ cmd: 'stop', out })

    }

}

问题是在一个进程通过msg.cmd = 'stop'告诉主进程停止后,没有办法return输出msg.out。它在上面的代码中实现的方式是,return msg.out 语句位于嵌套在较大的 diversify 函数中的匿名函数中。因此,当您 运行 类似于 diversify(() => { return true }) 时,此 return 值不会公开,从而导致 undefined。有什么方法可以 return msg.out 中发送的内容吗?

向工作人员发送消息是异步设计的。

技术上无法 return 来自作为事件处理程序的回调的值,因为事件可能随时发生。

此问题的规范解决方案是 promises。只需将函数体包装在一个 promise 和 resolve 值中而不是返回它。

const diversify = (f) =>
    new Promise((resolve) => {
        // Split a function `f` into a thread for each core of the machine.
        // The first thread to finish will return its result and end all others.

        if (cluster.isMaster) {
            let children = [];
            for (let i = 0; i < os.cpus().length; i++) {
                children.push(cluster.fork());
            }

            cluster.on('message', (_, msg) => {
                if (msg.cmd == 'stop') {
                    children.forEach((child) => {
                        child.process.kill();
                    });
                }
                resolve(msg.out);
            });
        } else {
            let out = f();
            process.send({ cmd: 'stop', out });
        }
    });

然后可以在 out:

中访问结果
const getPid = () => {
    return process.pid;
};

diversify(() => {
    console.log(getPid());
    return true;
}).then((out) => {
    console.log(out); // true
});

// or using async/await

const diversifyAsync = async () => {
    const out = await diversify(() => {
        console.log(getPid());
        return true;
    });

    console.log(out); // true
};

diversifyAsync();