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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8413857/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 05:54:59  来源:igfitidea点击:

Whats the smartest / cleanest way to iterate async over arrays (or objs)?

javascriptnode.js

提问by Aron Woost

Thats how I do it:

我就是这样做的:

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");
});

Is it any good? How to avoid those spaghetti'ish code?

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

采纳答案by alessioalex

Checkout the asynclibrary, it's made for control flow (async stuff) and it has a lot of methods for array stuff: each, filter, map. Check the documentation on github. Here's what you probably need:

查看异步库,它是为控制流(异步内容)而设计的,它有很多用于数组内容的方法:每个、过滤器、映射。查看github上的文档。以下是您可能需要的:

each(arr, iterator, callback)

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

Applies an iterator function to each item in an array, in parallel. The iterator is called with an item from the list and a callback for when it has finished. If the iterator passes an error to this callback, the main callback for the eachfunction is immediately called with the error.

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

eachSeries(arr, iterator, callback)

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

The same as eachonly the iterator is applied to each item in the array in series. The next iterator is only called once the current one has completed processing. This means the iterator functions will complete in order.

each仅将迭代器串联应用于数组中的每个项目相同。只有在当前迭代器完成处理后才会调用下一个迭代器。这意味着迭代器函数将按顺序完成。

回答by Maxim

As pointed in some answer one can use "async" library. But sometimes you just don't want to introduce new dependency in your code. And below is another way how you can loop and wait for completion of some asynchronous functions.

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

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);

Now, running node iterasync.jswill wait for about three seconds and then print [ 'ONE', 'TWO', 'THREE' ]. This is a simple example, but it can be extended to handle many situations.

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

回答by georg

As correctly pointed out, you have to use setTimeout, for example:

正如正确指出的那样,您必须使用 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) })

回答by Daniel Herr

The easiest way to handle async iteration of arrays (or any other iterable) is with the await operator (only in async functions) and for of loop.

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

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

You can use a library to convert any functions you may need which accept callback to return promises.

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