I'm trying to use writeFile() inside call back function of readFile() from fileSystem module..
I'm a beginner in node.js I have been watching Youtube tutorials
const fs = require('fs');
fs.readFile('readMe.txt','utf8', function(err, data){
fs.writeFile('writeMe.txt', data);
});
console.log('Fire..');
I get an error pasted below.. I don't understand the type of this error.. can someone help me with this?
Fire..!
fs.js:128
throw new ERR_INVALID_CALLBACK();
^
TypeError [ERR_INVALID_CALLBACK]: Callback must be a function
at maybeCallback (fs.js:128:9)
at Object.writeFile (fs.js:1163:14)
at C:\Users\shahzaib laptops\Desktop\NodeJS\pathModule\fileSystem.js:6:6
at FSReqWrap.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:53:3)
You can use the Following snippet to read and write file what need. You this in common and use this if u need in many place. u need to pass the filename to read and write to this method.
Else directly use the callback alone the parameter in method and jsut give the file name static as u have above.
public ReadandWriteFile(fileNameToRead, fileNameToWrite, callback) {
fs.readFile(fileNameToRead, "utf-8", (err, data) => {
if (err) { console.log(err) }
if (data) {
fs.writeFile(fileNameToWrite, data, (err) => {
if (err) { console.log(err) };
if (data) {
callback({ message: 'Successfully Written to File.' })
}
});
}
})
}
Add proper err handling and callback Fn. in writefile
const fs = require('fs');
fs.readFile('readMe.txt','utf8', function(err, data){
if(err) callback or return err
else{
fs.writeFile('writeMe.txt', data,'utf8', function(err2, data2){
if(err2) callback or return err2
else console.log(data2)
});
}
});
console.log('Fire..');
You can use promise for readFile and writeFile.
const fsPromises = require("fs").promises;
async function readAndWrite() {
let filehandle;
try {
filehandle = await fsPromises.readFile("readMe.txt");
console.log(filehandle);
let writeComleted = await fsPromises.writeFile("writeMe.txt", filehandle);
} catch {
throw new Error("something bad happened");
}
}
readAndWrite();
Related
I am a beginner to node.js and I have been following an online course when I received this error: TypeError [ERR_INVALID_CALLBACK]: Callback must be a function. Received undefined
fs.writeFile(fileDescriptor, function (err) {
if (!err) {
fs.close(fileDescriptor, function (err) {
if (!err) {
callback('false');
} else {
callback('Error closing existing file');
}
});
} else {
callback('Error writing to existing file');
}
});
I am pretty sure that I have already included a callback here. How should I solve this?
You are not providing a callback function to fs.writeFile (should be the third argument) and the second argument for fs.writeFile should be the data which you want to write.
const fs = require('fs');
const data = "Text, text and more text.";
function callback(err) {
if (err)
console.log(err);
else {
console.log("File written successfully\n");
}
}
fs.writeFile("file.txt", data, callback);
More info:
callbacks: https://codeburst.io/javascript-what-the-heck-is-a-callback-aba4da2deced
fs.writeFile: https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#fswritefilefile-data-options-callback
I have looked at a couple of other answers, but they did not help me.
node version 16.8.0
windows 10
"got": "11.8.2",
electron 14.0.0
Here is what I am trying. The code below does download the file but createWriteStream throws error --
Uncaught (in promise) TypeError [ERR_INVALID_RETURN_VALUE]: Expected
AsyncIterable or Promise to be returned from the "destination"
function but got type undefined.
Code in my render file
module.exports.getTile = async function (url, outputFilePath) {
const pipeline = promisify(stream.pipeline);
await pipeline(
got.stream(url),
fs.createWriteStream(outputFilePath),
(err) => {
if (err) {
console.error('Pipeline failed', err);
} else {
console.log('Pipeline succeeded');
}
});
stream.finished(input, (err) => {
if (err) {
console.error('Stream failed', err);
} else {
console.log('Stream is done reading');
}
});
};
I call the function with await getTile(url, tilePath);
stream.pipeline(...streams, callback) accepts n stream middlewares and a final callback argument as per documentation.
util.promisify(...args, callback) accepts a function with an error-first callback and wraps it into an async function that throw on errors. (docs)
When the two are combined, util.promisify will consume the final callback argument in stream.pipeline, and return an async function that only accept stream middlewares: util.promisify(stream.pipeline)(...streams).
Consequently, the following snippet
await pipeline(
got.stream(url),
fs.createWriteStream(outputFilePath),
(err) => {
if (err) {
console.error('Pipeline failed', err);
} else {
console.log('Pipeline succeeded');
}
});
Should be rewritten as:
try {
await pipeline(
got.stream(url),
fs.createWriteStream(outputFilePath)
)
console.log('Pipeline succeeded');
}
catch( error ){
console.error('Pipeline failed', err);
}
I have the following code:
updateDocument = (data) => {
Cloudant(CONN_STRING, (err, cloudant) => {
if (err) {
throw new Error('Failed to initialize Cloudant: ' + err.message);
}
let db = cloudant.db.use('my-db')
db.insert(data, (err, result) => {
if (err) {
throw new Error('Failed to initialize Cloudant: ' + err.message);
}
else {
console.log(result);
}
})
});
}
I would like for updateDocument() to return the result db.insert provides. However, if I try to return a variable it is undefined (I believe because of the async calls). I've tried async and await, but I may not have set them up properly because they also didn't work.
Thanks for any help!
This is a "JavaScript is asynchronous" problem. You could simplify your updateDocument function like so:
updateDocument = (data) => {
var cloudant = Cloudant({ url: CONN_STRING, plugin: 'promises');
let db = cloudant.db.use('my-db')
return db.insert(data);
}
This is using the Cloudant library with the "promises" plugin. JavaScript Promises help you manage asynchronous calls without passing callback functions around.
You would call this code like so:
updateDocument({a: 1, :b})
.then((data) => {
console.log('success!', data);
}.catch((e) => {
console.log('oops!', e);
});
Success arrives at 'then', failure arrives in the 'catch' clause.
I am new to nodejs and trying to cat multiple css files on-the-fly while coding. The package chokidar allow me to call a function when a file is modified, however I have a problem with the execution.
var goconcat =
fs.readdir(paths, function (err, files) {
if (err) {console.log(err);}
fs.unlink(paths + 'concat.css', function (err) {
if (err) throw err;
var list = files.map(function (files) {
return path.join(paths, files);
});
concat(list, paths + 'concat.css', function(err) {
if (err) throw err
});
});
});
I want to first delete the previous file, then read the directory and then write a new "concat.css". However I have an error;
Error: ENOENT: no such file or directory, open 'public/css/concat.css'
at error (native)
It appears that the function concat() is executed before the directory update and not after, and therefore it is trying to cat a file that just have been deleted. Why ?
I know that nodejs is executing functions in a synchronous way but I can't find a way to solve this problem. I tried async but I can't declare a variable between two functions and I couldn't manage to make it work.
If it cannot exist in a callback, using the setTimeout(fn, 0) trick may help make sure it's executed after the variable assignment.
var goconcat =
fs.readdir(paths, function (err, files) {
if (err) {console.log(err);}
fs.unlink(paths + 'concat.css', function (err) {
if (err) throw err;
var list = files.map(function (files) {
return path.join(paths, files);
});
setTimeout(function() {
concat(list, paths + 'concat.css', function(err) {
if (err) throw err
})}, 0);
});
});
The problem you're having is that your concat function is being invoked before the file is deleted by invoking unlink. You can prevent this by having nested callbacks; however, you can probably have better control flow if you use a module like async, and prevent yourself from dealing with Callback Hell.
Below is an example on how you can use the async module.
var fs = require('fs');
var async = require('async');
var myDir = __dirname + '/data';
async.waterfall([function(callback) {
fs.readdir(myDir, 'utf-8', function(error, files) {
if (error) {
return callback(error);
}
return callback(null, files);
});
}, function(files, callback) {
fs.open(myDir + '/myFile', 'wx', function(error, f) {
if (error && error.code === 'EEXIST') {
return callback(null, 'EEXIST');
}
return callback(null, 'CREATE');
});
}, function(fileStatus, callback) {
if (fileStatus === 'EEXIST') {
console.log('File exists. Deleting file...');
fs.unlink(myDir + '/myFile', function(error) {
if (error) {
return callback(error);
} else {
return callback(null);
}
});
} else {
console.log('File does not exist...');
return callback(null);
}
}, function(callback) {
fs.writeFile(myDir + '/myFile', "Hello World", function(err) {
if(err) {
return callback(error);
}
return callback(null, 'File Created');
});
}], function(error, results) {
console.error(error);
console.log(results);
});
The waterfall function runs the tasks array of functions in series,
each passing their results to the next in the array. However, if any
of the tasks pass an error to their own callback, the next function is
not executed, and the main callback is immediately called with the
error.
I'm trying to use NodeJS to read a txt file by using fs. This is the code of app.js:
var fs = require('fs');
function read(file) {
return fs.readFile(file, 'utf8', function(err, data) {
if (err) {
console.log(err);
}
return data;
});
}
var output = read('file.txt');
console.log(output);
When i do:
node app.js
It says
undefined
I have fs installed and there is a file.txt in the same directory, why is it not working?
Your read function is returning the result of the fs.readFile function, which is undefined because it doesn't have a return clause (it uses callbacks). Your second return clause is in an anonymous function, so it only returns to that scope. Anyhow, your function knows its finished after that first return.
The standard way to use fs.readFile is to use callbacks.
var fs = require('fs');
function read(file, callback) {
fs.readFile(file, 'utf8', function(err, data) {
if (err) {
console.log(err);
}
callback(data);
});
}
var output = read('file.txt', function(data) {
console.log(data);
});