我有一个关于原生数组的问题。JavaScript的每一个实现都是异步的吗? 例如,如果我调用:
[many many elements].forEach(function () {lots of work to do})
这将是非阻塞的吗?
我有一个关于原生数组的问题。JavaScript的每一个实现都是异步的吗? 例如,如果我调用:
[many many elements].forEach(function () {lots of work to do})
这将是非阻塞的吗?
当前回答
虽然数组。forEach不是异步的,你可以得到异步的“最终结果”。在下面的例子:
delayFunction(x) { 归还新承诺( (resolve) => setTimeout(() => resolve(x), 1000) ); } [1,2,3].forEach(async(x) => { console.log (x); console.log(等待delayFunction (x)); });
其他回答
如果您需要一个异步友好的Array版本。对于ach和类似的,它们在Node.js 'async'模块中可用: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中执行非常繁重的计算有一个常见的模式,可能适用于你…
Node是单线程的(作为一个深思熟虑的设计选择,请参阅什么是Node.js?);这意味着它只能利用一个核心。现代的盒子有8个、16个甚至更多的内核,所以这可能会使90%以上的机器闲置。REST服务的常见模式是为每个核心启动一个节点进程,并将这些进程放在本地负载均衡器(如http://nginx.org/)后面。
Forking a child - For what you are trying to do, there is another common pattern, forking off a child process to do the heavy lifting. The upside is that the child process can do heavy computation in the background while your parent process is responsive to other events. The catch is that you can't / shouldn't share memory with this child process (not without a LOT of contortions and some native code); you have to pass messages. This will work beautifully if the size of your input and output data is small compared to the computation that must be performed. You can even fire up a child node.js process and use the same code you were using previously.
例如:
var child_process = require('child_process'); function 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(); }
虽然数组。forEach不是异步的,你可以得到异步的“最终结果”。在下面的例子:
delayFunction(x) { 归还新承诺( (resolve) => setTimeout(() => resolve(x), 1000) ); } [1,2,3].forEach(async(x) => { console.log (x); console.log(等待delayFunction (x)); });
编辑2018-10-11: 看起来下面描述的标准很有可能无法通过,可以考虑管道作为替代方案(虽然行为不完全相同,但方法可以在类似的庄园中实现)。
这就是为什么我对es7感到兴奋,在未来你将能够做一些像下面的代码(一些规格不完整,所以使用时要小心,我会尽量保持最新)。但是基本上使用新的::bind操作符,你将能够在对象上运行一个方法,就好像对象的原型包含了这个方法一样。例如[Object]::[Method],通常你会调用[Object].[ObjectsMethod]
注意今天(7月24日-16日)要做到这一点,并让它在所有浏览器中都能工作,你需要编译以下功能的代码:导入/导出,箭头函数,承诺,Async / Await,以及最重要的函数绑定。如果必要,下面的代码可以修改为只使用函数绑定,所有这些功能今天都可以使用babel。
YourCode.js(其中“许多工作要做”必须简单地返回一个承诺,在异步工作完成时解决它。)
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;
});
};
数组中。forEach是用来计算东西而不是等待的,并且在事件循环中使计算异步是没有任何收获的(如果你需要多核计算,web工作者会添加多处理)。如果希望等待多个任务结束,可以使用计数器,可以将计数器包装在信号量类中。