Node.js 在节点中处理长时间运行的同步/阻塞任务的更好方法是什么

Node.js 在节点中处理长时间运行的同步/阻塞任务的更好方法是什么,node.js,child-process,event-loop,Node.js,Child Process,Event Loop,假设我们想找到一个很长的数组中所有数字的和。有两种方法可以在不阻塞事件循环的情况下完成 使用子进程使用节点 创建一个异步函数来添加并使用它来查找所有数字的总和 import awaitEach from 'await-each'; function makeItAsync(myFunc){ return function(...args){ return new Promise(function(resolve,reject){ setImmediate(function

假设我们想找到一个很长的数组中所有数字的和。有两种方法可以在不阻塞事件循环的情况下完成

  • 使用子进程使用节点

  • 创建一个异步函数来添加并使用它来查找所有数字的总和

    import awaitEach from 'await-each';
    
    
    function makeItAsync(myFunc){
     return function(...args){
    
       return new Promise(function(resolve,reject){
         setImmediate(function(){
           var result = myFunc(...args);
           resolve(result);
         });
      });
    
     }
    }
    
    function add(a,b){ return a + b}
    
    var asyncAdd = makeItAsync(add);
    
    var list = [1,2,3,4,5,6,7,8,9.........];
    var sum = 0;
    
    await awaitEach(list, async function(n){
        sum = await asyncAdd(n,sum);
    })
    
    console.log(sum);
    
  • 在阵列中异步使用asyncAdd和循环是执行长时间运行任务而不阻塞的解决方案之一

    想知道哪一个性能更好(cpu、内存)

    • 在大量请求的情况下,这是一种更好的方法
    • 哪一个更快
    • 哪一个需要更多的记忆
    setImmediate()
    setTimeout()
    可能会使某些内容变得异步,因为它们不会立即阻塞,但它们并不能真正解决长时间运行的阻塞任务的问题。他们将任务安排在以后运行,但当它运行时,它仍然是一个长时间运行的任务,会阻止事件循环,直到它完成为止。因此,您的
    makeItAsync()
    函数实际上并不比使用
    setTimeout()
    运行原始函数更有用

    如果您有一个长时间运行的任务,并且不想长时间阻止事件循环,那么以下是您的主要选项:

  • 将长时间运行的任务分解为非常小的工作,每个工作都可以在几毫秒内完成。完成一项工作后,使用短的
    setTimeout()
    计划下一项工作,这将允许事件循环处理工作之间的其他事件。这通常需要对长时间运行的任务(几乎是状态机)进行重大重写,有时对于某些类型的处理来说,很难进行架构和维护

  • 启动一个子进程并将长时间运行的任务分配给子进程。然后,您的主事件循环就完全并没有长时间运行的任务了。子进程可以在完成后返回结果。如果您必须经常运行此任务,则可以创建一个工作队列和一组子进程,这些子进程将咀嚼队列中的任务,并在任务完成时将消息发送回父进程。这通常相当容易做到。有一个缺点是子进程不能直接访问主进程中的数据,因此如果长时间运行的任务需要访问主进程中的大量数据,那么您必须设计一种共享数据的方法(可能将数据放入另一个进程,例如redis,多个进程可以访问它)


  • @PatrickRoberts打勾后,它将再次调用asyncAdd,并且该过程将再次继续搜索答案。我想我在我的问题中没有说得很清楚,但实际上我正在分解我长期运行的任务,将N个数字的列表添加到N个异步任务中。asyncAdd是将在循环中串行调用的函数。在问题中添加了更多的代码,以便更好地解释它