JavaScript: Await for a recursive tree to finish, where each recursive level is an API call

I’m trying to build a JSON tree using recursive API calls but I am having issues with flow control of the data structure. How can I block the flow until the BuildTree function stack ends?

Here is the partial code. Thanks in advance.

//FIRST CALL TO RETRIEVE THE ROOT
function callFW() {
    d3.json(url, function(data) { //?<----- api call
            Tree["uid"] = data.request.uid
            Tree["hid"] = data.firmware.meta_data.hid
            Tree["size"] = data.firmware.meta_data.size
            Tree["children"] = [];
            
            BuildTree(data.firmware.meta_data.included_files,Tree["children"])
            //WAIT FOR BUILDTREE
            console.log(Tree)
        } 
}

The BuildTree function is something like this:

async function BuildTree(included_files, fatherNode){ 
        if( included_files.length > 0){
            promises = [];

            included_files.forEach(function(item) {
                url = endpoint+"file_object/"+item+"?summary=true";
                promises.push(axios.get(url));
            });

            Promise.all(promises).then(function (results) {
                results.forEach(function (response) {
                    
                    var node = {}
                    node["uid"]= response.data.request.uid
                    node["hid"]= response.data.file_object.meta_data.hid
                    node["size"] = response.data.file_object.meta_data.size
                    node["children"] = []

                    fatherNode.push(node)

                    BuildTree(response.data.file_object.meta_data.included_files, node["children"])
                    


                });
            });
        }
    }

Answer

You are using the async keyword for no reason, because you are not using await inside your function. You might as well use it 🙂

async function BuildTree(included_files, fatherNode) {
    if (included_files.length > 0) {
        let promises = [];

        included_files.forEach(function (item) {
            url = endpoint + "file_object/" + item + "?summary=true";
            promises.push(axios.get(url));
        });

        const results = await Promise.all(promises);

        for(let response of results){

            var node = {}
            node["uid"] = response.data.request.uid
            node["hid"] = response.data.file_object.meta_data.hid
            node["size"] = response.data.file_object.meta_data.size
            node["children"] = []

            fatherNode.push(node)

            await BuildTree(response.data.file_object.meta_data.included_files, node["children"]);
        };
    }
};

And then you can simply await BuildTree :

function callFW() {
    d3.json(url, async function(data) {
            Tree["uid"] = data.request.uid
            Tree["hid"] = data.firmware.meta_data.hid
            Tree["size"] = data.firmware.meta_data.size
            Tree["children"] = [];
            
            await BuildTree(data.firmware.meta_data.included_files,Tree["children"]);

            console.log(Tree)
        })
}