So I am confused about how the function(err, data) callback works, is the first argument always an error handler?
What about the remaining arguments if you had something like function (x, y, z, a, b, c)?
How does the data from fs.readFile pass from the top line of code to the bottom line of code? Or in other words, how does the output of fs.readFile get put into the data argument?
fs.readFile(pathToFile, function (err, **data**) {
bufferString = **data**.toString();
I could replace function (err, data) with function (x, y) and function (x, y, z, a, b, c)
But only the second argument works (data and y), is this just the syntax of javascript callbacks?
For example, this is working code to asynchronously read a file and print out the number of lines given a file:
var fs = require('fs');
var pathToFile = process.argv[2];
var bufferString, bufferStringSplit;
function counter(callback) {
fs.readFile(pathToFile, function (err, data) {
bufferString = data.toString();
bufferStringSplit = bufferString.split('\n');
callback();
});
}
function logMyNumber() {
console.log(bufferStringSplit.length-1);
}
counter(logMyNumber);
Easy to understand with an example... you can write your own version of a function that uses a callback, quite simply:
Here, the function
getTwoStringsAsync
is pre-supposing that "callback" is a function, and it implies signature (two parameters that are strings). The consumer of your method is free to adhere to the implied signature or not. It can use one or both of those values, or neither. But if it assumes any more than two parameters, those will appear as undefined.It is arguably a limitation, or a strength, or weakly-typed languages like Javascript, that function signatures will not be verified. A strongly-typed language may generate a compiler error or warning in the first or third uses above.
When you call a function it can either return a single value or throw a single error.
So the "equivalent" of this synchronous code:
Is this asynchronous callback:
You can see now why it makes no sense to use multiple values in the callback. In fact, such pattern is actively harmful.
For example when using generators you are back to only having the possibility of using a single return value. But if some ignorant library author went ahead and broke the callback convention and used multiple, this would be impossible.
The arguments of the callback depend on how the callback gets called. For example:
Then you'd use it like:
The caller of the callback (which is the
readFile
method in this case) decides what arguments are passed to the callback. You need to declare your callback to match whatreadFile
says that it will pass to the callback. You can name the arguments anything you want (the names you use do not matter), but they will get values in the order thatreadFile
decides.In this case,
fs.readFile()
calls the callback with the two arguments you have in your code as incallback(err, data)
.Here's an example from the node.js docs: