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

2 Answers 2

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?

Sign up to request clarification or add additional context in comments.

Comments

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
        }
    })
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.