我有一个关于原生数组的问题。JavaScript的每一个实现都是异步的吗? 例如,如果我调用:
[many many elements].forEach(function () {lots of work to do})
这将是非阻塞的吗?
我有一个关于原生数组的问题。JavaScript的每一个实现都是异步的吗? 例如,如果我调用:
[many many elements].forEach(function () {lots of work to do})
这将是非阻塞的吗?
当前回答
这些代码片段将使您更好地理解forEach和forOf的比较。
/* eslint-disable no-console */ async function forEachTest() { console.log('########### Testing forEach ################ ') console.log('start of forEachTest func') let a = [1, 2, 3] await a.forEach(async (v) => { console.log('start of forEach: ', v) await new Promise(resolve => setTimeout(resolve, v * 1000)) console.log('end of forEach: ', v) }) console.log('end of forEachTest func') } forEachTest() async function forOfTest() { await new Promise(resolve => setTimeout(resolve, 10000)) //just see console in proper way console.log('\n\n########### Testing forOf ################ ') console.log('start of forOfTest func') let a = [1, 2, 3] for (const v of a) { console.log('start of forOf: ', v) await new Promise(resolve => setTimeout(resolve, v * 1000)) console.log('end of forOf: ', v) } console.log('end of forOfTest func') } forOfTest()
其他回答
如果您需要一个异步友好的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
});
这是一个不需要第三方库就可以使用的简短异步函数
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);
};
不,它堵塞了。看一下算法的说明。
然而,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。
另一个选择可能是网络工作者。
使用的承诺。每个蓝鸟图书馆。
Promise.each(
Iterable<any>|Promise<Iterable<any>> input,
function(any item, int index, int length) iterator
) -> Promise
This method iterates over an array, or a promise of an array, which contains promises (or a mix of promises and values) with the given iterator function with the signature (value, index, length) where the value is the resolved value of a respective promise in the input array. Iteration happens serially. If the iterator function returns a promise or a thenable, then the result of the promise is awaited before continuing with next iteration. If any promise in the input array is rejected, then the returned promise is rejected as well.
如果所有的迭代都成功解决了,请保证。每一个都解析为原始数组。但是,如果一次迭代失败或出错,请保证。每一个都立即停止执行,并且不再处理任何进一步的迭代。在这种情况下,返回的是错误或被拒绝的值,而不是原始数组。
这种方法是用来消除副作用的。
var fileNames = ["1.txt", "2.txt", "3.txt"];
Promise.each(fileNames, function(fileName) {
return fs.readFileAsync(fileName).then(function(val){
// do stuff with 'val' here.
});
}).then(function() {
console.log("done");
});
在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(); }