Hugo Mori
Hugo Mori

Reputation: 23

fs.writeFile does not respect the order of execution of functions (it always executes last)

I started tinkering with JavaScript (Node) recently, and I'm having a problem with a function that performs file writing. This function is always executed last, regardless of the calling order, and I can't fix it, could someone help me? (For example, in the code below, the categorySumPrice() function should run after the createAndWriteFixedJsonFile() function, but it runs before) This is the program:

// *********************  CLASSES  ****************

class Produto {
    constructor(id, name, quantity, price, category) {
        this.id = id
        this.name = name
        this.quantity = quantity
        this.price = price
        this.category = category
    }
}

// *********************  Procedural  *************

// ------ Global variables

// vector of objects produto
var produtos = []
// file name
const fileName = "broken-database.json"
//fixed file name
const fixedFileName = "./arquivo.json"
// file open require
const fs = require("fs")

//Read and Writing modes, like C
/* 
r - Open file for reading
r+ - Open file for reading and writing
rs - Open file for reading synchronous mode
rs+ - Open file for reading and writing, synchronous mode

w - Open file for writing synchronous mode (if not exists file, created that)
wx - Open file for writing (if not exists file, dont created that)
w+ - Open file for writing and reading (if not exists file, created that)
wx+ - Open file for writing and reading (if not exists file, dont created that)

*/

// Fix JSON Part
// open broken database
var jsonFileName = openFile(fileName)
//read json file, fix, if necessary, and create objects produto
readFile(jsonFileName)
//save new JSON file fixed
createAndWriteFixedJsonFile(fixedFileName)

//sum price functions
categorySumPrice()


// *********************  FUNÇÕES  *************

// Open File
function openFile(_file_name) {
    try {
        console.log('********************************')
        console.log('*  Arquivo aberto com sucesso  *')
        console.log('********************************')

        return fs.readFileSync(_file_name, 'utf-8')
    } catch (err) {
        console.error(err)
    }
}

// Fix JSON File and create objects produto
function readFile(_json_File) {
    // Create produtos objects
    try {

        console.log('********************************')
        console.log('*   Os dados serão corrigidos, *')
        console.log('*   se necessário.             *')
        console.log('********************************')

        const data = JSON.parse(_json_File)

        for (var i in data) {

            produtos[i] = new Produto(parseInt(data[i].id), fixString(data[i].name),
                fixQuantity(data[i].quantity), fixPrice(data[i].price), data[i].category)

        }

        console.log('********************************')
        console.log('*   Dados obtidos com sucesso  *')
        console.log('********************************')
    }
    catch (err) {
        console.log(`Erro: ${err}`)
    }
}

// create and write fixed Json file
function createAndWriteFixedJsonFile(_fixedFileName) {
    try {
    fs.writeFile(_fixedFileName, JSON.stringify(produtos, null, 2), err => {
            if (err) {
                console.log(err)
            }
            else {
                console.log('********************************')
                console.log('*  Arquivo criado com sucesso  *')
                console.log('********************************')
            }
        })

    } catch (err) {
        console.error(err)
    }
}


function fixQuantity(quantityToFix) {
    let quantity

    if (isNaN(quantityToFix)) {
        quantity = 0
    }
    else {
        quantity = parseFloat(quantityToFix)
    }
    return quantity

}

function fixPrice(priceToFix) {
    return parseFloat(priceToFix)
}

// Fix string function
function fixString(stringToFix) {
    // Quatro tipos de erros conhecidos:
    /* 
        "a" por "æ", 
        "c" por "¢", 
        "o" por "ø", 
        "b" por "ß".
    */
    // o /g significará que todos os valores correspondentes serão substituídos.
    // por padrão, replace substitui somente a primeira ocorrência
    stringToFix = stringToFix.replace(new RegExp(/æ/g), "a");
    stringToFix = stringToFix.replace(new RegExp(/¢/g), "c");
    stringToFix = stringToFix.replace(new RegExp(/ø/g), "o");
    stringToFix = stringToFix.replace(new RegExp(/ß/g), "b");

    return stringToFix
}

function categorySumPrice() {
    let estoquePorCategoria = []
    let indice
    let countCategories = 0

    for (var i in produtos) {
        if (i === 0) {
            estoquePorCategoria[countCategories] = { categoria: produtos[i].category, valor: (produtos[i].quantity * produtos[i].price) }
            countCategories++
        }
        else {
            indice = estoquePorCategoria.indexOf(estoquePorCategoria.filter(function (obj) {
                return obj.categoria == produtos[i].category;
            })[0]);
            if (indice != -1) {
                estoquePorCategoria[indice].valor += (produtos[i].quantity * produtos[i].price)
            }
            else {
                estoquePorCategoria[countCategories] = { categoria: produtos[i].category, valor: (produtos[i].quantity * produtos[i].price) }
                countCategories++
            }
        }
    }

    console.log(estoquePorCategoria)
}

Upvotes: 2

Views: 899

Answers (3)

user16435030
user16435030

Reputation:

writeFile is an asynchronous function, which means that it will execute in parallel to other things. So:

  1. You call writeFile then it starts writing.
  2. The rest of your code continues executing while it's writing.
  3. The writeFile finishes writing.

In order to have it execute synchronously with your other code you need to use writeFileSync.

You should use writeFile when the rest of your code isn't dependent on that file and writeFileSync if it is.

Upvotes: 1

chrwahl
chrwahl

Reputation: 13110

fs.writeFile() is executed asynchronously meaning that categorySumPrice() comes ahead of createAndWriteFixedJsonFile() because it takes time to save the file.

To avoid this you need to call categorySumPrice() from the callback function in fs.writeFile():

// create and write fixed Json file
function createAndWriteFixedJsonFile(_fixedFileName) {
    try {
    fs.writeFile(_fixedFileName, JSON.stringify(produtos, null, 2), err => {
            if (err) {
                console.log(err)
            }
            else {
                console.log('********************************')
                console.log('*  Arquivo criado com sucesso  *')
                console.log('********************************')

                //And now is the time for executing the following:
                categorySumPrice();
            }
        })

    } catch (err) {
        console.error(err)
    }
}

Upvotes: 0

flyingturtles
flyingturtles

Reputation: 903

You can use fs.writeFileSync, this will run according to your work flow.

Learn more about it here - https://www.geeksforgeeks.org/node-js-fs-writefilesync-method/

Upvotes: 0

Related Questions