Reputation: 31
I'm a Javascript newbie, and I'm building small nodeJS programs to learn more about Javascript.
I have an issue with my code that I cannot seem to solve. My program basically looks like this.
While (exitProgram === false){
// user input
// If user input is 'save', save a file to the disk
// If user input is 'exit', exitProgram = false
};
The problem is that the file only saves to the disk after the while loop is exited. I know this has something to do with Asynchronous execution of the writefile function, but I don't know how to make sure the file is saved in the loop (or other solutions).
Do you have any ideas or suggestions on how to do this?
This is my code so far:
'use strict';
const prompt = require('prompt-sync')();
const fs = require('fs');
const filePath = 'c:/documents/writefiletest/';
let fileName = 'characters.txt';
var allCharacters = [];
let buildCharacter = function () {
let name = null, strenght = null, hp = null;
name = prompt('You want to make a new Character. What is the name? ');
strenght = prompt('And the strenght? ');
hp = prompt('And lastly the hitpoints? ');
let newChacacter = {
name: name,
strenght: strenght,
hp: hp
};
console.log('You created ' + name + ' with ' + hp + ' hitpoints and ' + strenght + ' strenght.')
return newChacacter;
}
let ShowAllCharacters = function (allCharactersToShow) {
let i;
if (allCharactersToShow.length === 0) {
console.log('There are no characters to return. \n')
return false;
};
for (i = 0; i < allCharactersToShow.length; i++) {
console.log(i + ': ' + allCharactersToShow[i].name + ' has ' + allCharactersToShow[i].strenght + ' strenght and ' + allCharacters[i].hp + ' hitpoints.');
};
};
let saveToFile = function (data) {
if (data.length == 0) {
saveFilemessage.sucess = false;
saveFilemessage.message = 'There are no characters to save';
return;
};
fs.writeFile(filePath.concat(fileName), JSON.stringify(data), function (err) {
if (err) {
console.log("this is the error " + err);
return;
} else {
console.log('File saved to ' + filePath.concat(fileName));
return;
};
});
}
// Main Loop
while (!exitProgram) {
let userCommand = null;
console.log('\nWhat would you like to do? (New) (Show All) (Save To File) (Open File) (Exit)');
userCommand = prompt('');
switch (userCommand.toLowerCase()) {
case 'new':
case 'n':
allCharacters.push(buildCharacter());
break;
case 'show all':
case 'show':
ShowAllCharacters(allCharacters);
break;
case 'exit':
case 'e':
exitProgram = true
break;
case 'save to file':
case 'save':
case 's':
saveToFile(allCharacters);
break;
case 'open file':
case 'o':
console.log('Still to build open file function here');
break;
};
setTimeout(function () { return }, 0);
};
Thanks!
Upvotes: 0
Views: 747
Reputation: 6724
When you call the writeFile it works asynchronously and you can not wait for it finished with callbacks.
In the JS world there several ways to solve this issue.
1. Use .writeFileSync
writeFileSync is synchronous and it will wait until the saving is done.
function saveToFile(data) {
if (data.length == 0) {
saveFilemessage.sucess = false;
saveFilemessage.message = 'There are no characters to save';
return;
};
fs.writeFileSync(filePath.concat(fileName), JSON.stringify(data));
}
2. Use async/await with Promise
Basically you can make your functions as promises and wait for them to be finished. It requires some knowledge to use them. Here is a simple example for you.
function saveToFile(data) {
return new Promise((resolve, reject) => {
if (data.length == 0) {
saveFilemessage.sucess = false;
saveFilemessage.message = 'There are no characters to save';
resolve(false);
};
fs.writeFile(filePath.concat(fileName), JSON.stringify(data), function (err) {
if (err) {
console.log("this is the error " + err);
reject(false);
} else {
console.log('File saved to ' + filePath.concat(fileName));
resolve(true);
};
});
})
}
async function callMyFunction(){
await saveToFile('yourData');
}
3. Stay in the loop until callback is called (don't use this JS is not C++)
let saveToFile = function (data, doneFn) {
if (data.length == 0) {
saveFilemessage.sucess = false;
saveFilemessage.message = 'There are no characters to save';
doneFn(false);
};
fs.writeFile(filePath.concat(fileName), JSON.stringify(data), function (err) {
if (err) {
console.log("this is the error " + err);
doneFn(false);
} else {
console.log('File saved to ' + filePath.concat(fileName));
doneFn(true);
};
});
}
// Main Loop
while (!exitProgram) {
let userCommand = null;
if(userCommand !== "SAVING"){
console.log('\nWhat would you like to do? (New) (Show All) (Save To File) (Open File) (Exit)');
userCommand = prompt('');
}
switch (userCommand.toLowerCase()) {
case 'new':
case 'n':
allCharacters.push(buildCharacter());
break;
case 'show all':
case 'show':
ShowAllCharacters(allCharacters);
break;
case 'exit':
case 'e':
exitProgram = true
break;
case 'save to file':
case 'save':
case 's':
userCommand = 'SAVING';
saveToFile(allCharacters, function(res){
if(res){
console.log('Saving is done');
}else{
console.log('Saving is failed');
}
userCommand = null;
});
break;
case 'open file':
case 'o':
console.log('Still to build open file function here');
break;
};
setTimeout(function () { return }, 0);
};
Upvotes: 2