【问题标题】:NodeJS: Asynchronous map for blocking jobsNodeJS:用于阻塞作业的异步映射
【发布时间】:2017-10-06 10:09:37
【问题描述】:

让我们举个例子,我有一个巨大的数组,其中的元素是字符串化的 JSON。我想遍历这个数组并使用 JSON.parse 将所有字符串转换为 JSON(这会阻止事件循环)。

var arr = ["{...}", "{...}", ... ]      //input array

这是第一种方法(可能会使事件循环阻塞一段时间):

var newArr = arr.map(function(val){
  try{
    var obj = JSON.parse(val);
    return obj;
  }
  catch(err){return {};}

});

第二种方法是使用async.map方法(这会比第一种方法更有效吗?):

var newArr = [];
async.map(arr, 
  function(val, done){
    try{
        var obj = JSON.parse(val);
        done(null, obj);
      }
      catch(err){done(null, {});}
  }, 
  function(err, results){
    if(!err) 
      newArr = results;
  }
);

如果第二种方法相同或几乎相同,那么在 node.js 中执行此操作的有效方法是什么。

我遇到了child processes,这是解决这个问题的好方法吗?

【问题讨论】:

  • "与第一种方法相比,这会有所改善吗?"改善什么?你想达到什么目的?
  • 高效是我猜的更好的词。编辑相同。
  • async 尽管有这个名字,但不会进行任何异步操作。它只是一个编排已经异步任务的工具。

标签: javascript json node.js asynchronous event-loop


【解决方案1】:

我不认为async.map 保证同步函数的非阻塞处理。尽管它用asyncify 函数包装了您的函数,但我在该代码中找不到任何实际上使它成为非阻塞的东西。这是我过去在使用 async 时遇到的问题之一(但现在可能有所改进)

您绝对可以使用子进程手动处理自己的解决方案,但使用 https://github.com/audreyt/node-webworker-threads 之类的方法可能更容易

【讨论】:

  • async 的文档指出:“出于性能原因,异步不防范同步迭代”。所以它本身不会“异步”迭代函数。
  • 感谢@robertklep,显然问题仍然存在。很奇怪,IMO。
  • 嗯,async 的全部意义在于处理 asynchronous 工作流;D 如果它以同步方式使用,您不妨根本不使用它(尽管文档确实显示了同步和异步代码混合的某些情况)。
  • 是的,但是与 Promises 一样,在很多情况下您不知道您是在使用阻塞代码还是非阻塞代码。幸运的是,承诺 do 确保它将完成异步。 Zalgo 是一个会被咬的卑鄙的 mofo。
  • 特别是在使用async 时,我认为代码是否异步通常很清楚。但是,是的,承诺消除了这部分的任何困惑:)
【解决方案2】:

使用async.map,但将回调包装在setImmediate(done)

我发现async 功能非常方便,但效率不高;如果映射计算非常快,则每 10 次通过 setImmediate 调用 done 一次,否则直接调用它会明显更快地运行。 (setImmediate 打断了调用栈,让给了事件循环,但是 setImmediate 的开销是不可忽略的)

【讨论】:

  • 有趣,直觉上是这样想的。
猜你喜欢
  • 2010-09-20
  • 2016-05-31
  • 2018-04-06
  • 1970-01-01
  • 1970-01-01
  • 2016-07-14
  • 1970-01-01
  • 2020-12-17
  • 2018-09-04
相关资源
最近更新 更多