knoxgon
knoxgon

Reputation: 1243

NodeJS- How to sequentially create a file and then read from?

I'm entirely new to NodeJS and this problem has been bugging me for days now. I'm pulling my hairs to find a working solution. I'm trying to get information from the database and pass it to a text file where I later read from it. I cannot do it sequentially. It always reads it first and then creates it. I don't know what way I should take to overcome the issue. Any working solution/ways will help tremendously.

My connection file that retrieves information from the database:

this.getInfo = function() {
return new Promise(function(resolve, reject){
  db.query('SELECT ai_code from user_code',
    function(err,rows){
      if(err)
        reject(err);
      resolve(rows);
  });
 });
}

module.exports = 
{
    getInfo: this.getInfo
}

Functions that calls the method to receive data.

function team1Code(){
    db.getInfo().then(function(result){
       var code = JSON.stringify(result[0]);
       var c = json2plain(code, options);
       c = c.replace('Ai_code:','');
       fs.writeFile('./scr1.js', c, { overwrite: true, encoding: 'ascii' },function (err) {
        if (err) return console.log(err);
       });
    });
}
function team2Code(){
    db.getInfo().then(function(result){
        var code = JSON.stringify(result[1]);
        var c = json2plain(code, options);
        c = c.replace('Ai_code:','');
        fs.writeFile('./scr2.js', c, { overwrite: true, encoding: 'ascii' },function (err) {
            if (err) return console.log(err);
        });
    });
}

Finally, this is where we try to read the content of the files.

vmHandler.init = function(apiValues) {
    team1Code();
    team2Code();
  // Team 1
    try{
      vmHandler.team1.scriptCode = fs.readFileSync('./scr1.js');
      vmHandler.team1.script = new vm.Script(vmHandler.team1.scriptCode);
      vmHandler.team1.sandbox = { api: new Api(apiValues, 1) }
      vmHandler.team1.context = new vm.createContext(vmHandler.team1.sandbox);
    }catch(err){}
  // Team 2
    try {
      vmHandler.team2.scriptCode = fs.readFileSync('./scr2.js');
      vmHandler.team2.script = new vm.Script(vmHandler.team2.scriptCode);
      vmHandler.team2.sandbox = { api: new Api(apiValues, 2) }
      vmHandler.team2.context = new vm.createContext(vmHandler.team2.sandbox);
    } catch(err) {
      console.log("ERROR: " + err);
    }
};

Upvotes: 0

Views: 1130

Answers (2)

nurulnabi
nurulnabi

Reputation: 459

The approach you are taking is slightly unfavorable since the function calls team1Code(); team2Code(); doesn't make sure to accomplish before the next try-catch block gets executed. This is because both the calls are asynchronous hence the next lines get executed before they finish even though they are working with promises. promises themselves are asynchronous, what they make easy is all the code inside any then won't be executed until the promises get settled but the rest of the code will be executed as usual. So, here is the way to do your tasks with updated code.

function writeFile(fileName,data){
    return new Promise(function(resolve, reject){
        var code = JSON.stringify(data);
        var c = json2plain(code, options);
        c = c.replace('Ai_code:','');
        fs.writeFile(fileName, c, { overwrite: true, encoding: 'ascii' },function (err) {
            if(err)
                reject(err);
            resolve();
        });
    })
}
//Finally, this is where we try to read the content of the files.

vmHandler.init = function(apiValues) {
    var files = ['./scr1.js','./scr2.js'];
    db.getInfo().then(function(result){
        var allPromise = [];
        for(var key in files){
            allPromise.push(writeFile(files[key], result[key]));
        }
        return Promise.all(allPromise);
    }).then(function(res){
      // Team 1
        try{
          vmHandler.team1.scriptCode = fs.readFileSync('./scr1.js');
          vmHandler.team1.script = new vm.Script(vmHandler.team1.scriptCode);
          vmHandler.team1.sandbox = { api: new Api(apiValues, 1) }
          vmHandler.team1.context = new vm.createContext(vmHandler.team1.sandbox);
        }catch(err){}
      // Team 2
        try {
          vmHandler.team2.scriptCode = fs.readFileSync('./scr2.js');
          vmHandler.team2.script = new vm.Script(vmHandler.team2.scriptCode);
          vmHandler.team2.sandbox = { api: new Api(apiValues, 2) }
          vmHandler.team2.context = new vm.createContext(vmHandler.team2.sandbox);
        } catch(err) {
          console.log("ERROR: " + err);
        }
    });
};

Upvotes: 1

Andre T
Andre T

Reputation: 529

In the wmHandler.init function, you are starting 2 asynchronous operations (querying and storing) and reading from the files that the aforementioned async operations should write.

However, the file reading is performed right after the 2 async operations are started. Therefore, it is expected that the files are read before written.

To resolve this, make team1Code and team2Code return Promises of their own, and do not read the files until they have been written.

team1Code().
    .then(team2Code)
    .then(readFiles)

Where readFiles is the function that does the file reading, and team1Code, team2Code return Promises that resolve when the files are written.

This answer explains the asynchronous callbacks in Javascript.

Upvotes: 0

Related Questions