简体   繁体   中英

Call a function in JS when a loop is done?

Is there a standard way of calling a function after many async work is done? I am looping through N files and i call a async function. After the loop i called done() which caused a bug until i realize its because work is still being done by the time the loop is over due to async calls.

Anyways instead of writing my own countdown code is there a standard way to say after all of these functions/async calls are finish call this code?

Create a counter to hold the number of things already processed (initially set to 0)

Then invoke your assync operations, passing to each of them a callback function that

  1. Increments the counter on the number of things done
  2. If the counter reached N, safely call done()

The basic idea is this but you might need to add some extra stuff for error handling.


If you are lucky enough to be using an assynchronicity library there might be functions to do this for you. For example, Dojo has dojo.DeferredList for this kind of synchronization.

I tend to use this sort of thing:

function TaskList(tasks, endOfTasksCallback) {
    this.doTasks = function () {
        var numTasks = tasks.length;
        function singleTaskCallback() {
            if (--numTasks == 0) {
                endOfTasksCallback();
            }
        }
        for (var i = 0; i < tasks.length; i++) {
            tasks[i](singleTaskCallback);
        }
    }
}

function createTask(taskIdx) {
    // a task is a function that does some work
    // for this demo it's simply a random wait
    return function (endOfTaskCallback) {
        var ms = Math.floor(Math.random() * 1000 * 5);
        var startTime = new Date().getTime();
        setTimeout(function () {
            var endTime = new Date().getTime();
            console.log("task " + taskIdx + " completed in " + (endTime-startTime) + "ms.");
            endOfTaskCallback();
        }, ms);
    }
}

var numTasks = 10;
var tasks = [];
for (var i = 0; i < numTasks; i++) {
    tasks.push(createTask(i));
}
new TaskList(tasks, function () {
    console.log("all done!");
}).doTasks();

and you get output like this:

task 3 completed in 215ms.
task 5 completed in 1365ms.
task 2 completed in 2020ms.
task 4 completed in 2360ms.
task 0 completed in 2595ms.
task 6 completed in 2940ms.
task 9 completed in 3220ms.
task 1 completed in 3515ms.
task 8 completed in 3560ms.
task 7 completed in 4845ms.
all done!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM