我有一个关于原生数组的问题。JavaScript的每一个实现都是异步的吗? 例如,如果我调用:

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

这将是非阻塞的吗?


当前回答

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

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。

另一个选择可能是网络工作者。

虽然数组。forEach不是异步的,你可以得到异步的“最终结果”。在下面的例子:

delayFunction(x) { 归还新承诺( (resolve) => setTimeout(() => resolve(x), 1000) ); } [1,2,3].forEach(async(x) => { console.log (x); console.log(等待delayFunction (x)); });

数组中。forEach是用来计算东西而不是等待的,并且在事件循环中使计算异步是没有任何收获的(如果你需要多核计算,web工作者会添加多处理)。如果希望等待多个任务结束,可以使用计数器,可以将计数器包装在信号量类中。

这些代码片段将使您更好地理解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
});