JavaScript循环承诺:使用参数数组迭代

3
我正在尝试循环遍历一组AsynWork,以便完成异步工作时不会使系统负荷过重。所以我尝试使用promises一个接一个地执行。我的问题是我需要遍历一组值,以便每个异步操作都能处理数组的每个值。我已经用这段代码做到了,但它只适用于我的特定情况。怎么让它适用于其他类型的数组?我已经看到一些解决方案,使用array.reduce和promises,但是无法弄清楚它们。我也看到了一些Q的例子,但没有使用,如果可以用简单的javascript实现就更好了。
我的代码:
function doSomething(ObjIn1, ObjIn2) {
    return new Promise(function(resolve, reject) {
        console.log("doSomething: ObjIn1: " + ObjIn1 + "  ObjIn2: " + ObjIn2);
        setTimeout(function() {
            console.log("doSomething Done: ObjIn1: " + ObjIn1 + "  ObjIn2: " + ObjIn2);
            resolve(ObjIn1, ObjIn2);
        }, 500);
    })
}

function LoopPromises(Function2Loop, functionOptions, Counter, Max) {
    console.log("Counter: " + Counter);
    if (Counter < Max) {
        Function2Loop.apply(this, [functionOptions[0][Counter], functionOptions[1]]).then(function() {
            Counter++;
            LoopPromises(Function2Loop, functionOptions, Counter, Max);
        });
    }
}

LoopPromises(doSomething, [
    ["A1", "A2", "A3"], "ARG2TESTE"
], 0, 3)
1个回答

6
你可能想得太多了 :) 带参数的函数与不带参数的函数闭合带参数的函数是一样的,因此:
a(1,2,3,4);

与...相同

(() => a(1,2,3,4))(); 

除了可能稍微慢一些外,我假设你需要为任意数量的Promises排队工作。如果你只需要对固定数量的Promise进行操作 - 只需在它们之间使用then即可。让我们看看如何实现:

// runs fn on the array elements in sequence, but 
function sequence(fns) { // fns - functions returning promises
    return fns.reduce((prev, nextFn) => { // 'fold' the array
        return prev.then(nextFn); // after the previous is done, execute the next
    }, Promise.resolve()); // start with an empty promise
}

请确保您先了解reduce。为方便起见,让我们先看一个没有使用它的例子:

function sequence(fns) { // fns - functions returning promises
    var queue = Promise.resolve();
    fns.forEach(fn => queue = queue.then(fn));
    return queue;
}

我们正在遍历我们的工作数组(函数),并按顺序一个接一个地执行它们,其中我们在前一个返回解决后,在承诺之后执行下一个。
值根据承诺解决(通过then)相互等待。这将使您能够执行以下操作:
sequence([
   () => new Promise(r => setTimeout(r, 500));
   () => console.log("I only run after the previous work completed");
]);

非常感谢您的见解。这是一个非常好的方法。有点难以看到函数如何被循环,但一旦你知道了,就很好。我不得不编辑一些代码才能正常工作: sequence([ () => doSomething("ObjIn1","ObjIn2"), () => console.log("在前面的工作完成后,我才运行") ]); - Jose Neto
现在我正在构建函数数组时遇到一些问题。我正在通过图像数组进行for循环处理,但是当我执行类似于SequenceOfEditImage.push(() => EditImage(imagesArray[i]))的操作时,会出现问题,因为i键不存在于序列函数中。有什么想法可以解决这个问题吗? - Jose Neto
我正在做类似于这样的事情: - Jose Neto
对于(var i = 0; (i < ImagesArray.length) ; i++) { SequenceOfEditImage.push( () => EditImage(ImagesArray[i]) );
}
- Jose Neto
那就是闭包循环问题 - 在你的例子中,i 是每个图像相同的值 - 并且是 imagesArray.length,所以它们都是 undefined。如果你把那个 var 改成 let,它就会工作(在 for 循环中)。参见 https://dev59.com/v3RB5IYBdhLWcg3wAjNH。 - Benjamin Gruenbaum
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接