0

I've a following situation:

I've an appendToFile() function that I wrote:

function appendToFile(text, file) {
        (function (e) {
            freeze();
            FileUtils.readAsText(file)
                .done(function (data) {
                    console.log("File data: " + data);
                    console.log("File text: " + e);
                    var text = data + e;
                    FileUtils.writeText(file, text, true)
                        .done(function () {
                            console.log("File saved. Text: " + text);
                            unfreeze();
                            //window.alert("File saved. Text: " + text);
                        })
                        .fail(function (err) {
                            console.error(err);
                            window.alert(err);
                        });
                })
                .fail(function (err) {
                    console.error(err);
                });
        })(text);
    }

This function needs to append some text to a file. It is called from this function:

function processAttrs(clazz) {
        //window.alert("Hello" + clazz.name + " " + clazz.length);
        var file = FileSystem.getFileForPath("/Users/XXX/" + clazz.name + ".txt");
        createFile(file, function () {
            for (var i=0; i<clazz.attributes.length; i++) {
                var attr = clazz.attributes[i];
                var text = "private " + attr.type + " " + attr.name + "\n";
                appendToFile(text, file);
            }
        });
    }

The problem is that FileUtils.readAsText(file) is called asynchronously, so some lines that need to be written to a file get lost.

freeze() and unfreeze() are just empty functions where I thought about implementing something to stop and resume the code execution, but this mechanism doesn't seem to exist in Javascript.

I thought about using a callback as I did with createFile(file) function. The problem is that I don't know what to pass in as a callback function since the code execution is inside the for loop.

I could think of the solution without the for loop, and handling the flow manually using callbacks, but I don't like it. There have to be a more elegant solution

FabioBranch
  • 175
  • 4
  • 19
user3362334
  • 1,980
  • 3
  • 26
  • 58

2 Answers2

0

There is couple approaches to solve this problem. You can use async/await so you can "block" your loop

function appendToFile(text, file) {
    return new Promise((resolve, reject) => {
        (function (e) {
            //...
        })(text);
    });
}

async function  processAttrs(clazz) {
    //window.alert("Hello" + clazz.name + " " + clazz.length);
    var file = FileSystem.getFileForPath("/Users/XXX/" + clazz.name + ".txt");
    createFile(file, async function () {
        for (var i=0; i<clazz.attributes.length; i++) {
            var attr = clazz.attributes[i];
            var text = "private " + attr.type + " " + attr.name + "\n";
            const result =  await appendToFile(text, file);
        }
    });
}

Or some kind of promise waterfall like shown here Is Node.js native Promise.all processing in parallel or sequentially?

ponury-kostek
  • 7,824
  • 4
  • 23
  • 31
0

Change your code and use the async/await syntax, like this.

async function appendToFile(text, file) {
    try {
        freeze();
        var data = await FileUtils.readAsText(file)
        console.log("File data: " + data);
        console.log("File text: " + text);
        var text = data + text;
        await FileUtils.writeText(file, text, true)
        console.log("File saved. Text: " + text);
        unfreeze();
        return;
    } catch (e) {
        console.log('Error', e)
    }
}

function processAttrs(clazz) {
    var file = FileSystem.getFileForPath("/Users/XXX/" + clazz.name + ".txt");
    createFile(file, async function () {
        for (var attr of clazz.attributes) {
            var text = "private " + attr.type + " " + attr.name + "\n";
            await appendToFile(text, file) //This will stop the loop until each file is completed
        }
    })
}
Fernando Carvajal
  • 1,869
  • 20
  • 19