简体   繁体   中英

Modifying external array variable from within forEach callback

I have come across similar questions, but none that quite fits my scenario.

In the code below, I am using the listContainers() function from the dockerode Javascript library, to list the ids of my Docker containers. The snippet is adapted from one on the dockerode README. The listContainers call works and the console.log line outputs the ids as expected. The problem is that I cannot push the container IDs into the array declared outside the function call - the result is that the array is still empty after the listContainers call.

I am not very experienced with Javascript, but I think this problem is due to attempting the push inside the callback function. The problem is that the listContainers is asynchronous, so this means that //CONSOLE LOG #2 actually executes before //CONSOLE LOG #1 .

How can I capture the id values into the ids array outside the function call?

//Here is where I want to store my container ids.
var ids = [];

//Here is the dockerode call
dockerCli.listContainers(function(err, containers) {

    containers.forEach(function(containerInfo) {

        //log shows the correct id
        console.log(containerInfo.Id);

        //Here I try to save the container id to my array
        ids.push(containerInfo.Id);
    });

    //CONSOLE LOG #1 Here I can see that the array has the correct values
    console.log("IDs: "+ids.toString());
});

//CONSOLE LOG #2 Shows that the array is empty
console.log("IDs: "+ids.toString());

With the help of other commenters, I realised that the listContainers call is asynchronous and there is simply no way to return a value from it.

So how to initialise and work with my ids array? I created my own function that wraps the dockerode listContainers call. This function then takes its own callback to do the work with the ids array. This allowed me to access the initialised ids array in my own callback, separating the functionality of processing the ids array from fetching the container list.

ids = [];

//Define my function that takes a callback function
//and just fetch the container ids
function getContainerJsonFromDocker(callback) {

    dockerCli.listContainers(function(err, containers) {

        containers.forEach(function(containerInfo) {
            console.log(containerInfo.Id);
            ids.push(containerInfo.Id);
        });
        return callback(ids);
    });
}

//Now call my function, and pass it an anonymous callback
//The callback does the processing of the ids array
getContainerJsonFromDocker(function(ids) {

    //This shows the array is initialised :)
    console.log("IDs: " + ids.toString());

    //Write my array to .json file
    var outputFilename = 'data.json';
    fs.writeFile(outputFilename, JSON.stringify(ids, null, 4),
            function(err) {
                if (err) {
                    console.log(err);
                } else {
                    console.log("JSON saved to " + outputFilename);
                }
            });
});

you dont need to pass the global variable ids along with callback try this,

//Here is where I want to store my container ids.
var ids = [];

//Here is the dockerode call
dockerCli.listContainers(function(err, containers) {

    containers.forEach(function(containerInfo) {

        //log shows the correct id
        console.log(containerInfo.Id);

        //Here I try to save the container id to my array
        ids.push(containerInfo.Id);
    });
});

//Shows that the array is empty
console.log("IDs: "+ids.toString());

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