JavaScript,Node.js:是Array.forEachasynchronous?

我有一个关于本地Array.forEach JavaScript实现的问题:它是否asynchronous? 例如,如果我打电话:

 [many many elements].forEach(function () {lots of work to do}) 

这会不会阻塞?

不,它阻塞了。 看看algorithm的规格 。

但是MDN上可能会有一个更容易理解的实现:

 if (!Array.prototype.forEach) { Array.prototype.forEach = function(fun /*, thisp */) { "use strict"; if (this === void 0 || this === null) throw new TypeError(); var t = Object(this); var len = t.length >>> 0; if (typeof fun !== "function") throw new TypeError(); var thisp = arguments[1]; for (var i = 0; i < len; i++) { if (i in t) fun.call(thisp, t[i], i, t); } }; } 

如果你必须为每个元素执行很多代码,你应该考虑使用不同的方法:

 function processArray(items, process) { var todo = items.concat(); setTimeout(function() { process(todo.shift()); if(todo.length > 0) { setTimeout(arguments.callee, 25); } }, 25); } 

然后用以下方式调用它:

 processArray([many many elements], function () {lots of work to do}); 

这将是非阻塞的。 该示例取自高性能JavaScript

另一种select可能是networking工作者

如果你需要Array.forEach和类似的asynchronous友好版本,可以在Node.js的“asynchronous”模块中使用: http ://github.com/caolan/async …作为奖励,这个模块也可以工作在浏览器中。

 async.each(openFiles, saveFile, function(err){ // if any of the saves produced an error, err would equal that error }); 

在Node中执行一个非常繁重的计算有一个常见的模式,可能适用于您…

节点是单线程的(作为一个有意的deviseselect,请参阅什么是Node.js? ); 这意味着它只能使用一个核心。 现代的盒子有8个,16个甚至更多的核心,所以这个可以让机器的90%以上的空闲。 REST服务的常见模式是为每个核心启动一个节点进程,并将其放在本地负载平衡器(如http://nginx.org/)之后; 。

分岔一个孩子 – 对于你正在做的事情,还有另外一个共同的模式,就是分出一个孩子的过程去做重要的事情。 好处在于,subprocess可以在后台执行大量计算,而父进程可以响应其他事件。 问题是,你不能/不应该与这个subprocess共享内存(不是没有很多扭曲和一些本地代码); 你必须传递消息。 如果input和输出数据的大小与必须执行的计算相比较小,这将会很好地工作。 你甚至可以启动一个孩子node.js进程,并使用你以前使用的相同的代码。

例如:

 var child_process = require('child_process');
函数run_in_child(array,cb){
     var process = child_process.exec('node libfn.js',function(err,stdout,stderr){
         var output = JSON.parse(stdout);
         cb(err,output);
     });
     process.stdin.write(JSON.stringify(array),'utf8');
     process.stdin.end();
 }

Array.forEach是用于计算不等待的东西,在事件循环中没有什么可以获得asynchronous的计算(如果你需要多核计算,Web工具添加多处理)。 如果你想等待多个任务结束,使用一个计数器,你可以包装在一个信号类。

这就是为什么我对es7感到兴奋,将来你可以做一些类似于下面的代码的东西(有些规范不完整,所以谨慎使用,我会尽量保持这个更新)。 但是基本上使用new :: bind操作符,您将能够在对象上运行方法,就好像对象的原型包含方法一样。 例如[Object] :: [Method]你通常会调用[Object] [ObjectsMethod]

注意今天(16 -16 -16)要做到这一点,并在所有的浏览器中都能运行,你需要为你的代码编译以下function: 导入/导出箭头函数Promisesasynchronous/等待和最重要的函数绑定 。 下面的代码可以被修改为只使用函数绑定,如果有必要的话,所有这些function都可以通过使用babel整齐地使用。

YourCode.js(其中“ 很多工作要做 ”只是简单地返回一个承诺,在asynchronous工作完成时解决)。

 import { asyncForEach } from './ArrayExtensions.js'; await [many many elements]::asyncForEach(() => lots of work to do); 

ArrayExtensions.js

 export function asyncForEach(callback) { return Promise.resolve(this).then(async (ar) => { for(let i=0;i<ar.length;i++) { await callback.call(ar, ar[i], i, ar); } }); }; export function asyncMap(callback) { return Promise.resolve(this).then(async (ar) => { const out = []; for(let i=0;i<ar.length;i++) { out[i] = await callback.call(ar, ar[i], i, ar); } return out; }); }; 

这是一个简短的asynchronous函数,不需要第三方库就可以使用

 Array.prototype.each = function (iterator, callback) { var iterate = function () { pointer++; if (pointer >= this.length) { callback(); return; } iterator.call(iterator, this[pointer], iterate, pointer); }.bind(this), pointer = -1; iterate(this); }; 

每个循环都有一个简单的asynchronous npm包。

 var forEachAsync = require('futures').forEachAsync; // waits for one request to finish before beginning the next forEachAsync(['dogs', 'cats', 'octocats'], function (next, element, index, array) { getPics(element, next); // then after all of the elements have been handled // the final callback fires to let you know it's all done }).then(function () { console.log('All requests have finished'); }); 

也是另一种变体的AAsync

甚至可以编写这样的解决scheme,例如:

  var loop = function(i, data, callback) { if (i < data.length) { //TODO("SELECT * FROM stackoverflowUsers;", function(res) { //data[i].meta = res; console.log(i, data[i].title); return loop(i+1, data, errors, callback); //}); } else { return callback(data); } }; loop(0, [{"title": "hello"}, {"title": "world"}], function(data) { console.log("DONE\n"+data); }); 

另一方面,它比“for”慢得多。

否则,优秀的asynchronous库可以这样做: https : //caolan.github.io/async/docs.html#each