I have a function that tests whether a file exists or not before editing it. I use fs.stat.
fs.stat('../fill/bower.json', function (err, stats) {
if (err) {
console.log('You don\'t have a ' + clc.red('bower.json') + ' file! Type ' + clc.bgBlack.white('touch bower.json') + ' to get started.');
return;
} if (stats.isFile()) {
var json = JSON.parse(fs.readFileSync('../bower.json', 'utf8')),
string = '\n Dependencies: ' + json;
fs.writeFile('../fill/README.md,', string, 'utf8');
console.log('it\'s saved!');
}
})
However, every time I run it (bower.json doesn't exist on purpose), it returns undefined before You don't have a bower.json file!. Why does this happen and how can I stop the function printing undefined?
Edit: for reference, here's my terminal window after running the command:
Why is undefined printed, and what do I do to have that not be displayed?
You're returning nothing or undefined from your reading function.
Gist for posterity
Related
I have this code which should read the current text file's contents and make a new line and write a new sentence in that line, it writes it but the line before that is just undefined.
const data = msg.author.tag + " bejelentkezett a bottal. " + d.toLocaleTimeString();
const currenttext = fs.readFile('output.txt', 'utf8', function(err, contents) {
fs.writeFile('output.txt', currenttext + '\n' + data, (err) => {
if (err) throw err;
})
});
readFile does not return anything. Instead you will be given the contents in your callback in the variable you named contents.
So change
fs.writeFile('output.txt', currenttext + '\n' + data, (err) => {
to
fs.writeFile('output.txt', contents+ '\n' + data, (err) => {
As a side note your error handling is a mess. Throwing an error from within a callback just leads to losing the error. Consider using the promise api with async/await instead to simplify your code or update your callbacks. https://nodejs.org/api/fs.html#fs_fs_promises_api
I am trying to write code that reads a file, counts the lines in it, and then adds another line with the line's number in the beginning. Like an index, basically. The problem is that the fs.appendFile() starts running before fs.readFile() is finished, but I am not sure as to why. Is there something I am doing wrong?
My code:
fs.readFile('list.txt', 'utf-8', (err, data) => {
if (err) throw err;
lines = data.split(/\r\n|\r|\n/).length - 1;
console.log("Im supposed to run first");
});
console.log("Im supposed to run second");
fs.appendFile('list.txt', '[' + lines + ']' + item + '\n', function(err) {
if (err) throw err;
console.log('List updated!');
fs.readFile('list.txt', 'utf-8', (err, data) => {
if (err) throw err;
// Converting Raw Buffer dto text
// data using tostring function.
message.channel.send('List was updated successfully! New list: \n' + data.toString());
console.log(data);
});
});
My output:
Im supposed to run second
List updated!
Im supposed to run first
[0]first item
Currently, you are using readFile and appendFile. Both of these functions are asynchronous and will run at the same time, returning whenever they complete.
If you'd like to run these synchronously, you can use the fs.readFileSync and fs.appendFileSync methods to synchronously read and append to the files.
Therefore, with something like the following:
const readFileData = fs.readFileSync("list.txt");
fs.appendFileSync('list.txt', '[' + lines + ']' + item + '\n');
The first line of code will run, then the second line of code.
The functions you are using are asynchronous, so the response of the second function can be received before the response of the first one.
fs.readFile('list.txt', 'utf-8', (err, data) => {
if (err) throw err;
lines = data.split(/\r\n|\r|\n/).length - 1;
console.log("Im supposed to run first");
appendFile(lines);
});
let appendFile = (lines)=> {
fs.appendFile('list.txt', '[' + lines + ']' + item + '\n', function(err) {
console.log("Im supposed to run second");
if (err) throw err;
console.log('List updated!');
fs.readFile('list.txt', 'utf-8', (err, data) => {
if (err) throw err;
// Converting Raw Buffer dto text
// data using tostring function.
message.channel.send('List was updated successfully! New list: \n' + data.toString());
console.log(data);
});
});
}
I have simple little program which defines two functions as variables. These functions both return RSVP Promises so that they can be chained together as I have done below. I use this pattern often but in this case I'm running into madness ...
var opChown = function() { ... };
var opChgrp = function() { ... };
debug('chown: ' + opChown);
debug('chgrp: ' + opChgrp);
// Chain permission operations
opChown()
.then(opChgrp())
.then(function() {
debug('resolving parent promise');
resolve();
})
.catch(function(err) {
debug('rejecting parent promise');
reject(err);
}
);
While my debug statements clearly show that the two functions are in fact defined, when I execute them I get an unhandled exception:
TypeError: undefined is not a function
Please help me losing my mind. Any and all suggestions welcome.
For some additional context here is the definition of opChown:
var opChown = function() {
return new RSVP.promise(function(resolve,reject) {
debug('opChown');
if(options.ignoreChown) {
resolve();
} else {
var chown = shell('chown',['-R', downgradedUser, destDir]);
debug('chown command executed; user permission is "%s"', downgradedUser);
chown.on('exit',function(code) {
if(code !== 0) {
var errMessage = 'Build [' + code + ']:' + ' problems changing ownership on "' + destDir + '" directory to ' + downgradedUser + '.';
debug('Problem with chown: %s', code);
reject({operation:'chown', message: errMessage});
} else {
console.log(' - %s executed, user permissions changed to %s', chalk.bold('chown'), chalk.bold(downgradedUser));
resolve();
}
}); // end chown
}
});
}; // end opChgOwn
Now based on #bergi's great pointer that the stacktrace is indeed available to me on Node's 'uncaughtException' event, here is the stacktrace which clearly points to the problem being within the opChown function rather than the function itself:
TypeError: undefined is not a function
at opChown (/lib/broccoli-watcher.js:117:13)
at ChildProcess.<anonymous> (/lib/broccoli-watcher.js:167:5)
at ChildProcess.emit (events.js:98:17)
at Process.ChildProcess._handle.onexit (child_process.js:809:12)
Although I had expected the error message to be something like undefined is not a constructor, it looks as if the line
return new RSVP.promise(function(resolve,reject) {
should rather be
return new RSVP.Promise(function(resolve,reject) {
// ^
Notice that #SLaks spotted a mistake as well: then takes callback functions. You probably want to use
opChown().then(opChgrp)…
.then(opChgrp())
You just called opChgrp immediately and passed its result to then().
Since it doesn't return anything, you get an error.
I am trying to use imagemagick to resize my images, then passing it off to image compression tools to compress. I am trying to utilize pngquant`
Here is a snippet of my code:
// Rename and move original file
if (fs.existsSync(tmpPath + '/' + file)) {
fs.renameSync(tmpPath + '/' + file, filePath + '/' + fileName);
// Create new versions of each file
Object.keys(geddy.config.uploader.imageVersions).forEach(function (version) {
console.log(version);
counter += 1;
var opts = geddy.config.uploader.imageVersions[version];
console.log(fileName);
imageMagick.resize({
width: opts.width,
srcPath: filePath + '/' + fileName,
dstPath: filePath + '/' + fileName.replace(/\.[^/.]+$/, "") + '_' + version + fileType
}, finish(filePath + '/' + fileName.replace(/\.[^/.]+$/, "") + '_' + version + fileType));
});
} else {
console.log('Unable to find tmp file!');
}
Then here is my callback finish:
finish = function (file) {
execFile(pngquantPath, ['256', '--force', file], function(err, data) {
console.log(err, data);
});
};
However, every time pngquant it is saying there is no file found. If I take the parameter file and go into the shell, run pngquant file, it runs the process. So I am assuming it is an asynchronous issue (files not there, it tries to run the process).
This is the error I end up with in the console:
{ [Error: spawn EACCES] code: 'EACCES', errno: 'EACCES', syscall: 'spawn' } ''
Any help is appreciated.
imageMagick.resize() expects two arguments: an options object and a callback.
For the second argument, you are not passing finish as your callback. Instead, you are invoking finish and passing whatever finish returns (probably undefined) as the callback argument.
Because you are invoking finish at the same time you make the resize() call, it is running immediately, before ImageMagick can complete its resize operation.
Try changing the resize() line to something like this:
imageMagick.resize({
// (your resize options)
},
function(err) {
if (err) { return console.error(err); } // whatever error handling you need
var thePath = filePath + '/' + fileName.replace(/\.[^/.]+$/, "") + '_' +
version + fileType;
finish(thePath);
});
Now you’re passing a callback function as the second argument, and that function will not be invoked until imageMagick.resize() is done. And of course it has the signature of all Node callbacks, which is that the first argument to the callback is err. When it’s invoked, the callback does some error-checking and then calls finish.
I'm comparing the output of childprocess.exec to a string, but I must have overlooked something since I didn't get the expected result.
function download_all(list, callback){
var i=0, cmd="";
function afterDownload(){...}
while(i<list.length)
{
cmd="[ -f ./downloads/"+list[i]+" ] && echo \"E\" || echo\""+list[i]+"\"";
exec(cmd, function(error, stdout, stderr){
if(stdout=="E")
{
console.log("Already Exist");
}else{
console.log("download "+LINK+""+stdout);
download(LINK+stdout, afterDownload());
}
});
i=i+1;
}
Basically, I check if a file exist, look at the output of the command, and if it is not E (which sign the file exist), download it.
The problem is, even when the file exist, the app try to download LINK+E, which doesn't exist and of course fail.
I've tried with === instead of ==, and " instead of ', but it didn't changed anything.
Is there some character in stdout other than E?
NodeJS has the "fs" module which takes care of that for you. The documentation is at http://nodejs.org/api/fs.html
You can do this:
fs.exists(list[i], function (exists) {
console.log("exists = ", exists);
});