Reading a file - fileName is not defined [error] - javascript

I am completely new to JavaScript, and I am having a trouble with using fs.readFile() function.
I am required to read a file, and determine whether I have to call successFn (when err boolean is false) or errorFn (if err boolean is true).
When I err is false, however, I am trying to call an "extractor" function as a parameter -- extractor separates the data read into each word.
I am required to call fs.readFile, so I am required to use parameters and one of the parameters is fileName.
The grader is going to test my code using his own files, so I am not supposed to define fileName, yet I am being asked to define it (I understand why I am being asked to do it, but I feel that there should be a way to get around this issue.)
Also, JavaScript syntax is very not intuitive, so I might be making some mistakes with the syntax, but here is my code, and please let me know how I can fix my issue:
function readAndExtractWith(extractor) {
fs.readFile(fileName, 'utf-8', (err, data) => {
if (err) {
errorFn(err);
}
else {
data = extractor();
successFn(data);
}
return extractor;
});
}

fileName is not defined because you never define it. Since you are using that in a function you need to either pass the variable as an argument, specify it inside the function, or define it globally.
var fileName = "stackoverflow.jpg";
// when executing the function pass the fileName parameter
readAndExtractWith(extractor, fileName);
function readAndExtractWith(extractor, fileName) {
fs.readFile(fileName, 'utf-8', (err, data) => {
if (err) {
errorFn(err);
}
else {
data = extractor();
successFn(data);
}
return extractor;
});
}

Related

Wanted help in understanding how parameters are defined in Callback functions, using this example (if possible)

I am trying to understand more on how callback functions work in JavaScript.
I found this simple example code online and after adding the imports & additional txt file it's working. However I am not sure why it is working as the parameters of the functions aren't being defined anywhere?
fs.readFile(`${__dirname}/temp.txt`, (err, data) => {
console.log(`Breed: ${data}`);
superagent.get(`https://dog.ceo/api/breed/${data}/images/random`).end((err,res) =>{
console.log(res.body)
}); })
Upon running this I get the expected result on the console with the line displaying Breed: ${data} and the next line showing the body of the res.
However, the err, data parameters have never been provided to the arrow function within readFile. Neither has the err,res parameters ever been called/provided a value for it to display a message to the console, then how are these lines displaying a message to the console?
I could have understood this working if .readFile returned a err and data value & .end returned a err and res value, however upon reading the documentation both these functions return void, thus i'm confused and help would be appreciated.
You pass a function in to readFile, and later on readFile will call your function. When it calls your function, readFile will pass in the relevant values.
You can do something similar yourself, like this:
function myReadFile(filename, callback) {
setTimeout(() => {
if (Math.random() > 0.5) {
callback(null, 'fake file');
} else {
callback('an error', null);
}
}, 1000);
}
myReadFile(`${__dirname}/temp.txt`, (err, data) => {
console.log(`Breed: ${data}`);
})
(though of course the real readFile function isn't doing timeouts or random numbers, but rather reading from a file and listening for that operation to succeed or error out)

Optional paramters in Vanilla-javascript

I dont know how to make function arguments to be optional in a certain case.
The case is if I have at more than one argument and not the last one should be optional. I see the ejs templating engine solves this:
ejs.renderFile(templatesPath, options, (err, html) => {
if (err) {
console.log(err);
error = err;
} else {
res.write(html);
res.end();
}
})
So if I dont pass the options paramter, the callback function will still be recognized as a callback function and not as the options object - and the role, assigned to it, remains to be callback function and not the role of the missed paramter - as it would normally.
So how can it be solved - in Javascript - that I still define 2-3 or more arguments (in the function definition) but if I dont pass an optional one - which is not the last - that it doesnt change the passed paramters role.
Thanks
What matters is the order of the parameters. Therefore, you must repect it.
Just pass undefined, null or an empty object {} if the function does not support no value.
Below, options is declared but not valued (undefined). The order is respected, it will work.
You can keep this way: always declare variable to pass them to the function, and assign value to them only when you have it.
var options;
ejs.renderFile(templatesPath, options, (err, html) => {
if (err) {
console.log(err);
error = err;
} else {
res.write(html);
res.end();
}
});

javascript callbacks - handle reading a file with fs.readFile

For a project, I am using the net module to create a 'mini web framework'
I'm having a lot of trouble dealing with this one callback
var sendFile(path) {
fs.readFile(path, config, this.handleRead.bind(this));
}
where readFile is defined as:
var handleRead = function(contentType, data, err) {
if (err) {
console.log(err); //returns properly
} else {
console.log(data); //returns properly
console.log(contentType) //returning undefined
}
So far this code works in the sense that I can catch errors and also write the data properly.
My question is : how do I send the contentType through the call back?
I've tried -
var sendFile(path) {
var contentType = ContentType['the path type']
fs.readFile(path, config, this.handleRead(contentType).bind(this));
}
But then this causes data and err to be undefined.
I'm quite new to js and am still confused about how to work with callbacks. Any input is appreciated!
.bind() lets you do more than just set the "context" (this value of a function). You can also "bind" arguments in the function.
Try:
function sendFile(path) {
var contentType = ContentType['the path type']
fs.readFile(path, config, this.handleRead.bind(this, contentType));
}
This will pass a callback with its context set to whatever this is and its 1st parameter set to contentType. As long as this callback is called with data (and possibly err), then everything will work.

How are callback functions' parameters dependent on ordering?

Let's say I have an event I'm waiting for in Javascript, where we'll have something like this:
fileSystem.readFile('done', function(err, data){
//do something with the file
});
In this situation, the parameters err and data are arbitrarily named and ordered, so they could have been in another order
function(data, err) {/*do something*/ }
How does data get passed the data and err get passed any errors?
I notice this pattern to be pervasive everywhere through out javascript callbacks, and it is largely a mystery to me how function parameters are passed in a predictable order without following some convention I must not be aware of.
How does this work?
What happens is that when you call
fileSystem.readFile('done', function(err, data){
//do something with the file
});
the function you pass as the second parameter will be saved for later use (when the file is finished reading). It will then call the function you passed for you, with a possible error value as the first parameter, and the file contents as the second parameter.
readFile = function(event, callback) {
var error = null;
var fileContents = /* read file implementation. Maybe error will be assigned some value here */;
callback(error, fileContents);
}
Of course, this is just some pseudo-code to illustrate my point.
Now, you can name your parameters in your function function(err, data) whatever you want, because they are in the scope you defined. Even if you swap their names function(data, err), they will still contain the error and file content values respectively.

node.js nodeschool learnyounode need help understanding the code of the solution

Question - the exercise from NODESCHOOL.IO;LEARNYOUNODE;MAKE_IT_MODULAR reads directory and filters files by a given file extension - uses a module to do most of the work. Question on the added code referenced below. First time see this - but i take it from this example you are able to add code to an already defined function when you call it. But want to clarify if I understand the execution of it. Is it the callback function - noted below that allows this "added" code to be executed? Thanks
solution.js:
var filterFn = require('./solution_filter.js')
var dir = process.argv[2]
var filterStr = process.argv[3]
filterFn(dir, filterStr, function (err, list) {
if (err)
return console.error('There was an error:', err)
// QUESTION ON THIS PART OF THE CODE - see below in the module part of the program
list.forEach(function (file) {
console.log(file)
})
})
// THIS IS THE MODULE FOR THE PROGRAM
solution_filter.js:
// require file system module
var fs = require('fs')
module.exports = function (dir, filterStr, callback) {
var regex = new RegExp('\\.' + filterStr + '$')
fs.readdir(dir, function (err, list) {
// callback err if the readdir method fails
if (err)
return callback(err)
list = list.filter(function (file) {
return regex.test(file)
})
// IS THIS CALLBACK SO IT LOOP AND IS ABLE TO EXECUTE ADDED CODE in the solution.js filterFn()
callback(null, list)
})
}
Thinking about it as "adding code to an already defined function" isn't really accurate. You're passing in a completely different function as the callback parameter. The code in the module is written to expect that, and it invokes the function you pass in.
Your function doesn't have access to the code in the module, and the module doesn't have access to the code in your function.
Creating functions on-the-fly and passing them as parameters to other functions is a very common pattern in JavaScript.

Categories

Resources