downloadPhoto('http://coolcats.com/cat.gif', handlePhoto)
function handlePhoto (error, photo) {
if (error) console.error('Download error!', error)
else console.log('Download finished', photo)
}
console.log('Download started')
I know handlePhoto as a callback passed into downloadPhoto, but I'm confused with handlePhoto function itself, the first parameter is error, is that means js recognize it as an error? can I use "err" replace or other parameter name.And what is the second parameter in console.log means, I can't find exactly answer for it yet.
When downloadPhoto function invocation is completed, it calls handlePhoto with some parameters.
According to convention ( rule generally followed ), first parameter should always be error & rest can be result values.
function downloadPhoto(url , callback ){
if(gotImageFromRemoteSuccessfully){
callback(null,successResponse)
} else{
callback(whatWentWrong , null );
}
}
the first parameter is error, is that means js recognize it as an error?
No, it means that when that function is called, the first argument passed to it will be placed in a variable named error.
can I use "err" replace or other parameter name
Yes. You can call the arguments whatever you want according to the normal rules of argument naming.
And what is the second parameter in console.log
That is the second thing that you want to be logged. console.log takes any number of arguments and logs them all.
Thanks everyone, I think if I add callback && callback(error ,result) in side downloadPhoto function, it would be more clear for me. But there is a follow up question here I saw many functions which don't have callback && callback(), how could these function pass parameter to its callback function?
Related
I have a block of code like that
function doA (callback) {
//do something...
callback();
}
function doB (callback) {
//do something...
callback();
}
function doC () {
//do something...
}
i know it's a bad practice and have to avoid it, but i am trying to understand why when i called the functions as
doA(doB(doC)));
it throwed an error that "callback is not a function" ?
But when i tried:
doA(doC);
everything was ok.
edited: i have tried to use chrome dev tool to figure out how javascript callstack works here, and i found out that the call stack be like:
doC
doB
there isn't doA function, so why js avoids adding doA() to the callstack?
it throwed an error that "callback is not a function" ?
You call doA and pass the return value of doB(doC) as the first argument.
doB has no return statement, so it returns undefined.
doA tries to call the first argument (which has the value undefined) as a function, which it isn't, so it fails.
It isn't entirely clear what you are trying to achieve (since your example code has been abstracted so much), but you should probably investigate the Promises API which would let you do something like:
doA().then(doB).then(doC);
You are passing result of doB(doC) as the argument of doA but it is not a function:
doB(doC); // undefined
doA(undefined); // throws: callback is not a function
For callback you need to pass function and doB(doC) will execute it and will return undefined. And that undefined value will get passed to doA(undefined) and thats why you are getting -
callback is not a function
because doB it's not returning a function.
that expression means that the output of doB is passed as argument to doA, but since doB is not returning a function you get the error.
Sorry if this question is too naive to ask or already been answered. I am confused about javascript anonymous callback function which can access data returned by calling function. E.g:
var server = http.createServer(function(request, response){
response.writeHead(200, {'Content-Type': 'text/html'});
response.write('hello world');
response.end();
});
Can anyone explain how anonymous function's arguments are accessing the data returned by http.createServer() function? Or I am getting something wrong? Apologies in advance for any mistake as this is my first question here.
The outer function is getting the callback as argument, and it calls it with some arguments. Maybe a simpler example will explain it better:
There is a function that takes another function as an argument, and calls it with a 'value' string passed as argument:
function fn(cb) {
cb('value');
}
Now when you run:
fn(function (val) {
console.log(val);
});
you will have the string 'value' printed but not because the second (anonymous) function has access to variables or values inside of the fn function, but because the anonymous function got some data passed as its argument - called val in this example.
The data isn't returned by createServer.
createServer will, at some point in the future, call the function and pass it arguments at the time.
You can't see the code that does that (well, you can, since Node.js is open source and you could dig it out if you really wanted to), but you don't need to since its behaviour is documented.
Compare to this:
var thing = example_that_takes_a_callback(function(request, response) {
console.log(request, response);
});
function example_that_takes_a_callback (callback) {
callback(1,2);
setTimeout(function () { callback(3,4); }, 1000);
setTimeout(function () { callback(5,6); }, 2000);
return 1;
}
Simply : the anonymous function you pass as an argument to createServer() is being called inside the code of this latter with the appropriate arguments request & response.
I'm currently learning about callbacks in Node and JavaScript in general and am getting confused by the following:
var request = require('request');
request('http://www.google.com', function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body) // Show the HTML for the Google homepage.
}
})
My question is this: How does the request function know what each parameter/argument is in the callback? Because I could effectively call the function callback with two parameters and skip out the error? How would the function know that the first parameter passed was the response and not the error, for instance?
Does it do checks on the types of each at runtime or? Thanks.
The programmer who wrote the request API decides the order of the parameters sent to the callback. There is no type checking at runtime. If you were to supply only two arguments in your callback signature, e.g.
function(response, body) {}
you would still be receiving the error object and the response -- only in this case, the variable named "response" would hold the error object, and the variable named "body" would hold the response. The input you would be skipping would be the third one you didn't supply, the body. The names of your parameters make no difference, it is their position in the function signature that determines what value they will be assigned.
By convention, in javascript callbacks, the first parameter of the callback normally represents the error object. It is not always written this way, but it is a best practice.
Possibile implementation of this function could be:
function request (url, callback) {
// doing something
callback (error, response, body);
}
The function will set the value of error, response and body parameters. I don't know how it's is implemented, but suppose that you pass a number for the url. A possibile implementation could be:
function request (url, callback) {
if (typeof url === 'number') {
// Suppose that error is an instance of Error
callback (new Error ('Url must be a string'), null, null);
}
// other stuff...
}
When you call the request() function, and provide a function as an argument, it calls that function internally (inside the module) and passes in it's own data as the arguments (which you then use to do various things). The data it passes in is data it generated itself, it's not data you're creating.
That is a callback.
There is a quetsion I answered a little while ago that goes more indepth as to why these modules are structured this way, see: npm's guidelines on callback errors
You are using a specific module my friend and callbacks are controlled in this case directly from it.
How the callback works for 'Request' module is matter of research. Check their documentation.
This is my piece of code, which works correctly (adds records), but throws an error after addition:
Uncaught Error: Invariant Violation: enqueueCallback(...): You called
setProps, replaceProps, setState, replaceState, or
forceUpdate with a callback that isn't callable.
handleSubmit: function(e) {
e.preventDefault();
return $.post('', {page: this.state},
function(data) {
this.props.handleNewPage(data);
return this.setState(this.getInitialState(), 'JSON');
}.bind(this)
);
}
There are no routes for now. Can someone help me to solve this?
The second (optional) parameter to setState is a callback function, not a string. You can pass a function that will be executed once the operation is completed.
You actually invoke getInitialState instead of providing a reference to the function itself on the line return this.setState(this.getInitialState(), 'JSON'); and the second argument should never be anything but a callback function.
this.setState expects either a function that should return a state object as a single argument, or an object to merge the current state with (plus optionally a callback as a second argument to run after state has been set). So either you provide just a function that returns the new state, or you provide an object that the current state should be merged with as a first argument and a callback that will be executed after the state has been set as second argument.
Either this.setState(this.getInitialState) or this.setState(this.getInitialState()) or this.setState(newState, callback).
Check out the signature in the API here.
I am having a hard time understanding how the callback() function is used in the following code block.
How are we using callback() as a function, in the function body, when function callback() has not been defined?
What are the repercussions of passing true / false as parameters into the callback function below?
I appreciate any clarification, thanks in advance!
socket.on('new user', function(data, callback){
if (nicknames.indexOf(data) != -1){
callback(false);
} else{
callback(true);
socket.nickname = data;
nicknames.push(socket.nickname);
updateUserList();
}
});
When you pass a function as an argument, it is known as a callback function, and when you return a value through this callback function, the value is a parameter of the passed function.
function myFunction(val, callback){
if(val == 1){
callback(true);
}else{
callback(false);
}
}
myFunction(0,
//the true or false are passed from callback()
//is getting here as bool
// the anonymous function below defines the functionality of the callback
function (bool){
if(bool){
alert("do stuff for when value is true");
}else {
//this condition is satisfied as 0 passed
alert("do stuff for when value is false");
}
});
Basically, callbacks() are used for asynchronous concepts. It is invoked on a particular event.
myFunction is also callback function. For example, it occurs on a click event.
document.body.addEventListener('click', myFunction);
It means, first assign the action to other function, and don't think about this. The action will be performed when the condition is met.
I agree with you, the code in the snippet is very unclear.
The answers you got are great, however none refers to the actual use of callback in your code, and I would like to reference that specifically.
First, I will answer your question, and then I will elaborate on the complexity of it.
The answer
turns out socket.io are doing something very cool which is not the standard I know..
socket.io are passing the callback from the front-end to the backend!
So to answer your question what is this callback function - you have to look at your frontend code.
Look for code that looks like this
socket.emit('new user', data, function( booleanParameter ){
// what are you doing with booleanParameter here?
});
I assume that in your case true/false values are meant to pass back to the frontend if new user was added (true) or not (false)..
Or perhaps if the nickname is already in use or not so that the frontend can show an error string if it is..
Basically, #SumanBogati was right in his answer, but I felt it was lacking the step of finding the callback in the front-end due to socket.io's special treatment.
Further Suggestion To make your code clearer
Change name of parameter data to nickname
Add comments - why are you placing nickname on socket?
add documentation
Use jsdocs to explain what the callback is doing
/**
#callback NewUserCallback
#param {boolean} booleanParameter does something..
**/
and then on the function itself
/**
#parameter {string} nickname
#parameter {NewUserCallback} callback
**/
The complexity
Usually, in nodejs, a callback expects the first argument to be an error, so reading your code, it says
socket.on('new user', function(data, callback){
if (nicknames.indexOf(data) != -1){
///// THERE IS NO ERROR
callback(false);
}else{
///// THERE IS AN ERROR
callback(true);
/// do more stuff after the error
socket.nickname = data;
nicknames.push(socket.nickname);
updateUserList();
}
});
Not the pattern you'd expect, is it? I guess this is why you asked the question.
Still the question remains what socket.io's callback means, right? Perhaps their callback does not expect an error as first argument.
I have never used socket.io, and I was unable to find a documentation to clarify this. So I had to download their chat example and debug it ==> and so the answer I gave, they are passing the function from the frontend to the backend.
Socket.io should definitely stress this point in large font in their documentation under a title named "How does socket.io handle callbacks?" or "How does our callbacks work?".
Great question! Learned a lot from it!
I'll try to simplify with a "concrete" example (I hope).
Let's say I have a function that "calculates" the current day and I'll call that function each time I would need the current day ("Don't call us, we'll call you" or whatever).
var getCurrentDay = function (callback) {
var currDate = new Date();
callback(currDate, 'err');
});
};
getCurrentDay(function (returnDay) {
logger.info('Today is: ' + returnDay); });
A callback function, is a function that is passed to another function (let’s call this other function “otherFunction”) as a parameter, and the callback function is called (or executed) inside the otherFunction.
Here is my simple example for callback function
// callback add
function add(a, b){
console.log(a+b);
}
// Main function
function getInput(cb) {
c = 5+5;
d = 6+6;
if (typeof cb === 'function') {
cb(c, d);
}
}
getInput(add)
For detailed explanation refer the this link
Without thinking too much, see the following example.
In the following example, I just call the print function from the add function.
function print( ans ){
console.log(ans) ; // 7
}
function add(a, b){
print(a+b) ;
}
add(2,5);
What if I use the print function as a parameter? Without using print function from global scope I just pass the print function as an argument.
function print( ans ){
console.log(ans) ; // 7
}
function add(a, b, callback){ // here callback = print
callback(a+b) ;
}
add(2,5,print); // print function as a parameter
Generally, JavaScript allows function as a parameter.
So any function that is passed as an argument is called a callback function.
I think now callback is understandable to you.
Callback function mean call after another:)
doHomeWork('math',alertMsg);
Above line said 1. call doHomeWork and then call 2. alertMsg, that's it.:)
function doHomeWork(subject,callback){
console.info("study: "+subject);
callback();
}
alertMsg = function(){
console.info("alert");
}
doHomeWork('math',alertMsg);
Output:
study: math
alert
A callback is any function that is called by another function using parameter
Here a query for you Suppose that Consider how programmers normally write to a file:
- `fileObject = open(file)` //now that we have to wait for the file to open, after that we can write to this file*
- fileObject.write("We are writing to the file.") // but i want to write , not wait
This case - where callbacks are helpful:
//we can pass **writeToFile()** (a callback function) to the open file function
- fileObject = open(file, writeToFile)
//execution continues flowing -- we do not wait for the file to be opened
//once the file is opened we can write to it, but while we wait we can do other things
Function inside a function is called a callback function. Or let me say that the inside function which is present inside the parent function is called the callback function.
If you want to complete a task2 after task1. Then you can make task2 as the callback and this will run asyncronously
Here is one example where the usage of callback function is easy to understand.
A login function which performs user login with the server asynchronously.
Due to asynchronous call , we need to get the result of login once the date receives from the server.
const axios = require('axios');
function login(loginData,callbackSuccess,callBackFailure) {
axios
.post("/api/login",loginData)
.then((response) => {
callbackSuccess(response);
})
.catch((error) => {
callBackFailure(error);
});
}
function callbackSuccess(data) {
console.log("Login response :",data);
}
function callBackFailure(error) {
console.log("Login failed :",error);
}
let userData = {
username : "test",
password : "abcd123"
}
login(userData,callbackSuccess,callBackFailure);