什么是在数组(或objs)上迭代异步的最聪明/最干净的方法?

Aro*_*ost 33 javascript node.js

多数民众赞成我怎么做:

function processArray(array, index, callback) {
    processItem(array[index], function(){
        if(++index === array.length) {
            callback();
            return;
        }
        processArray(array, index, callback);
    });
};

function processItem(item, callback) {
    // do some ajax (browser) or request (node) stuff here

    // when done
    callback();
}

var arr = ["url1", "url2", "url3"];

processArray(arr, 0, function(){
    console.log("done");
});
Run Code Online (Sandbox Code Playgroud)

这有什么好处吗?如何避免那些意大利面条的代码?

ale*_*lex 30

检查异步库,它是为控制流(异步东西)而制作的,它有很多方法用于数组:每个,过滤器,映射.查看github上的文档.这是你可能需要的:

每个(arr,迭代器,回调)

将迭代器函数并行应用于数组中的每个项目.使用列表中的项目调用迭代器,并在完成时调用它.如果迭代器将错误传递给此回调,each则会立即调用该函数的主回调并显示错误.

eachSeries(arr,iterator,callback)

each只有迭代器一样,串行应用于数组中的每个项目.只有当前的迭代器完成处理后才会调用下一个迭代器.这意味着迭代器函数将按顺序完成.


Max*_*xim 17

正如一些答案所指出的,可以使用"异步"库.但有时你只是不想在你的代码中引入新的依赖.下面是如何循环并等待某些异步函数完成的另一种方法.

var items = ["one", "two", "three"];

// This is your async function, which may perform call to your database or
// whatever...
function someAsyncFunc(arg, cb) {
    setTimeout(function () {
        cb(arg.toUpperCase());
    }, 3000);
}

// cb will be called when each item from arr has been processed and all
// results are available.
function eachAsync(arr, func, cb) {
    var doneCounter = 0,
        results = [];
    arr.forEach(function (item) {
        func(item, function (res) {
            doneCounter += 1;
            results.push(res);
            if (doneCounter === arr.length) {
                cb(results);
            }
        });
    });
}

eachAsync(items, someAsyncFunc, console.log);
Run Code Online (Sandbox Code Playgroud)

现在,运行node iterasync.js将等待大约三秒钟,然后打印[ 'ONE', 'TWO', 'THREE' ].这是一个简单的例子,但它可以扩展到处理许多情况.

  • 令人难以置信的是,这个答案对此评论的回答是零. (3认同)

geo*_*org 9

正确指出,您必须使用setTimeout,例如:

each_async = function(ary, fn) {
    var i = 0;
    -function() {
        fn(ary[i]);
        if (++i < ary.length)
            setTimeout(arguments.callee, 0)
    }()
}


each_async([1,2,3,4], function(p) { console.log(p) })
Run Code Online (Sandbox Code Playgroud)

  • 为什么在第二个`function()`之前有一个" - "(减号)? (8认同)
  • @AaronDigulla`-functions()`使立即函数被视为表达式.它与将函数包装在括号中并没有什么不同,这是使它成为有效表达式的另一种方式.请参阅:http://stackoverflow.com/questions/13341698/javascript-plus-sign-in-front-of-function-name (5认同)

Dan*_*err 5

处理数组(或任何其他可迭代对象)的异步迭代的最简单方法是使用 await 运算符(仅在异步函数中)和 for of 循环。

(async function() {
 for(let value of [ 0, 1 ]) {
  value += await(Promise.resolve(1))
  console.log(value)
 }
})()
Run Code Online (Sandbox Code Playgroud)

您可以使用库来转换您可能需要的任何接受回调以返回承诺的函数。