This question already has an answer here:
understanding the concept of javascript callbacks with node.js, especially in loops
(1 answer)
Closed 8 years ago.
I know this has been asked a million times, but I'm really trying to break down async Javascript functions and callbacks and its just not clicking. I'm looking at Max Ogden's Art of Node example which is this:
var fs = require('fs')
var myNumber = undefined
function addOne(callback) {
fs.readFile('number.txt', function doneReading(err, fileContents) {
myNumber = parseInt(fileContents)
myNumber++
callback()
})
}
function logMyNumber() {
console.log(myNumber)
}
addOne(logMyNumber)
Breaking this down, I understand that when addOne is invoked, it first kicks off fs.ReadFile which may take some time to complete.
What I don't get is, won't the code continue to callback() and execute logMyNumber (before myNumber has been added to) anyhow? What's stopping callback() from running before it should, which is the whole point? Or does callback() not happen until doneReading has happened? Are we supposed to assume that doneReading will be invoked when fs.readFile is "done"?
Thank you all for your patience in helping me with this very common question:)
"Are we supposed to assume that doneReading will be invoked when fs.readFile is "done"?"
You dont have to assume it, you can be pretty sure of it.
You can use logging to see how and in what order your code gets executed.
var fs = require('fs')
console.log("starting script");
console.log("message 1");
function addOne(callback) {
fs.readFile('number.txt', function doneReading(err, fileContents) {
console.log("finished loading the file");
console.log("message 2");
callback()
})
}
console.log("message 3");
//logMyNumber will be called after file has read
function logMyNumber() {
console.log("message 4");
}
console.log("message 5");
addOne(logMyNumber)
console.log("message 6");
//______________
A simpler way to understand the asyncronous behavior is to use all familiar timer
console.log("message 1");
var num = 2;
function something() {
console.log("message 2");
}
function somethingElse() {
console.log("message 3");
}
console.log("message 4");
setTimeout(something, 1000);
console.log("message 5");
setTimeout(somethingElse, 500);
//code will run 1 - 4 - 5 - 3- 2 not from top to bottom, and this way its obvious why.
//in file read its the same reason
This is the way the code will flow:
You call to addOne(logMyNumber) will be executed.
addOne will read a file and once the file has been read it will then
execute the code in the "doneReading" function which in turn will call your callback (which is logMyNumber)
See the second argument for fs.readFile? It's a function called doneReading.
fs.readFile will only execute doneReading when it has finished reading the file. When doneReading gets executed, the last line is to call callback(), which is a reference to the logMyNumber function in this case.
fs.readFile will call the given callback, ie. doneReading in your code after the reading has been finished. This is how Node.js generally works with the callbacks: you give the callback which is ran after finishing the asynchronous operation.
// callback is a parameter to addOne
// callback is a function, but functions are just objects in javascript
// so the addOne function just knows that it has one parameter, not that
// callback is a function
function addOne(callback) {
// callback is now captured in the closure for the doneReading function
fs.readFile('number.txt', function doneReading(err, fileContents) {
myNumber = parseInt(fileContents)
myNumber++
// callback is executed here
// But we are inside the doneReading function
// which is itself a callback to the fs.readFile function
// therefore, it does not get executed until the file has finished reading
callback()
})
}
// similarly, logMyNumber has not been called, it has just been defined
// as a function (object)...
function logMyNumber() {
console.log(myNumber)
}
// ...and passing logMyNumber to addOne here does not execute it
addOne(logMyNumber)
Does that clear it up?
Related
I have read a few articles regarding callback function. I understand how they presented like add a + b then give callback function. But I am doing same. I first declared the function then call it again I call the callback function, why it is not working in my case?
function me(callback){
console.log("1")
}
me(function(){
console.log(2)
})
I am expecting console.log 1 then console.log 2. I am getting only console.log 1
you are calling the callback function, it won't trigger automatically, that approach is so you can notify something using that callback function when your function ended something.
function me(callback) {
console.log("1")
// your process ended, lets notify
callback();
}
me(function() {
console.log(2)
})
You have to actually call the callback function inside the function it is passed to as argument:
function me(callback){
console.log(1)
callback();
}
me(function(){
console.log(2);
})
I think this is so basic so people maybe minus votes on this document, but even so this is so confused me about callback function in JavaScript.
function doSomething(callback){
setTimeout(hello,5000);
callback();
}
function hi(){
console.log("hi");
}
function hello(){
console.log("hello");
}
doSomething(hi);
/* result */
// hi
// (after 5 seconds) hello
I want to use callback function as a handle function's execute order, so I decided use callback pattern. In above code, I think after 5 seconds, the callback function should be executed, but why callback ignore before function and was ran first? Could you tell me a some hint.
Thanks.
In your code callback() was executing after the execution of the line setTimeout() but the callback of setTimeout will trigger after 5000ms, that is the expected behaviour. So if you want callback() to exeute after hello() do:
function doSomething(callback){
setTimeout(function(){
hello();
callback();
},5000);
}
I'm very new to Javascript programming and was researching ways in dealing with asynchronous functions. I came across really helpful resource which lists this as an example:
var fs = require('fs')
var myNumber = undefined
function addOne(callback) {
fs.readFile('number.txt', function doneReading(err, fileContents) {
myNumber = parseInt(fileContents)
myNumber++
callback()
})
}
function logMyNumber() {
console.log(myNumber)
}
addOne(logMyNumber)
However could you achieve the same result doing this:
var fs = require('fs')
var myNumber = undefined
function addOne() {
fs.readFile('number.txt', function doneReading(err, fileContents) {
myNumber = parseInt(fileContents)
myNumber++
logMyNumber()
})
}
function logMyNumber() {
console.log(myNumber)
}
addOne()
And if you can, what would be the purpose/advantage of using callbacks?
For those interested the article came from here: https://github.com/maxogden/art-of-node#callbacks
When we use call back it depend on situation in to make things dynamic or make sure that a code of piece run after one is complete.in your current code already describe callbacks
your first example clearly state how we define callbacks.
In computer programming, a callback is a piece of executable code that is passed as an argument to other code, which is expected to call back (execute) the argument at some convenient time. The invocation may be immediate as in a synchronous callback, or it might happen at later time as in an asynchronous callback
var fs = require('fs')
var myNumber = undefined
you are using call back here which give you power to run different- different method after reading number.txt successfully
function addOne(callback) {
fs.readFile('number.txt', function doneReading(err, fileContents) {
myNumber = parseInt(fileContents)
myNumber++
callback()
})
}
in your second example there is no callback you are calling logMyNumber() directly, what if we need to run another function something like
function logMyNumber() {
console.log(myNumber)
}
function varifynumber() {
console.log(myNumber)
}
function somthingelse() {
console.log(myNumber)
}
addOne(logMyNumber)
addOne(somthingelse)
addOne(logMyNumber)
and the other best use of callbacks in JavaScript is handle asynchronous tasks, if you noticed
inside your function you are using fs.readFile('number.txt',callback) which is a asynchronous method please have look below example
console.log('start');
fs.readFile('number.txt', function doneReading(err, fileContents) {
// until the file not read completely this section will not run
// this happend because of call back
console.log('Reading complete');
})
console.log('End');
output :
start
End
Reading complete
i hope this will help you
It all depends on what you are trying to achieve. In the first example, the function addOne has no concept on what the callback parameter does, it just invokes it.
However, in the second case, the addOne function knows it will invoke logMyNumber, and therefore has a tighter coupling and concept of what exactly is going on.
The first example is often favorable in most cases, e.g. if you are splitting functions across multiple files, and don't want them to be tightly intertwined.
I am reading various tutorials on javascript with callbacks, but they are not clarifying a basic principle. What I understand is that when a function is called with a callback, this makes it possible to wait on execution of some code, and after that execute the callback function. So
// function definition
do_func(int num, callback)
{
Console.log(num);
..
..
callback();
}
//call the function
do_func(123, function(){
Console.log("Running callback");
});
So during execution of do_func, all lines of code are executed, and then callback() is executed. However if our function changed as
// function definition
do_func(int num, callback)
{
read file...
..
..
callback();
}
Then the callback would be called while the file is being read. So our purpose is defeated. What is happening here?
Thanks very much!
JavaScript itself is synchronous and single-threaded. You cannot write an asynchronous function.
What you can do is use some APIs provided by your environment (Node.js, Web browser) that allow you to schedule asynchronous tasks... timeouts, ajax, FileAPI to name a few.
An example using setTimeout (provided by the HTML Timing API):
window.setTimeout(function() {
console.log("World");
}, 1000);
console.log("Hello");
What is a simple example of an asynchronous javascript function?
do_func(int num, callback)
{
readFile(... , callback);
}
I'd expect that you're readFile function can also take a callback so you could just pass it along until the file has been read.
You are correct that in your example callback() would be called right away without waiting for the file to load. In JavaScript anytime something asynchronous is encountered you can generally listen for an event to know when to run the callback function.
Example loading an image:
var img = new Image();
img.addEventListener('load', callback); //add your listener first because if you ran the next line first it might load before your listener is setup
img.src = "fileondisk.jpg";
So i don't really understand the point of "callback".
Here is an example of callback:
function sayBye(){
alert("Bye!");
}
function saySeeYou(){
alert("See you!");
}
function sayHello(name,myfunc){
alert("Hello");
myfunc;
}
sayHello("Max",saySeeYou());
Whats the point of passing in a function when you can just call the function? like this code does the exact same:
function sayBye(){
alert("Bye!");
}
function saySeeYou(){
alert("See you!");
}
function sayHello(name){
alert("Hello");
saySeeYou();
}
sayHello("Max");
Whats the point of passing in a function when you can just call the function?
Usually, callbacks Javascript are used in Javascript for code that you want to run in the future. The simplest example is setTimeout: if you call the callback now then the code runs immedieately instead of after 500 ms.
//prints with a delay
console.log("Hello");
setTimeout(function(){
console.log("Bye");
}, 500);
//no delay this time
console.log("Hello");
console.log("Bye");
Of course, it would be really neat if we could write something along the lines of
//fake Javascript:
console.log("Hello");
wait(500);
console.log("Bye");
But sadly Javascript doesnt let you do that. Javascript is strictly single-threaded so the only way to code the wait function would be to pause the execution of any scripts in the page for 500 ms, which would "freeze" things in an unresponsive state. Because of this, operations that take a long time to complete, like timeouts or AJAX requests usually use callbacks to signal when they are done instead of blocking execution and then returning when done.
By the way, when passing callbacks you should only pass the function name. If you add the parenthesis you are instead calling the function and passing its return value instead:
//When you write
foo(10, mycallback());
//You are actually doing
var res = mycallback();
foo(10, res);
//which will run things in the wrong order
Your code is not correct as Felix Kling already pointed out. Besides this, passing a function instead of calling one directly allows you to insert different behavior, your code is more decoupled and flexible. Here an example:
function sayBye(){
alert("Bye!");
}
function saySeeYou(){
alert("See you!");
}
function sayHello(name,myfunc){
alert("Hello");
if (myfunc) {
myfunc();
}
}
sayHello("Max",saySeeYou);
// I'm inserting a different behavior. Now instead of displayng "See you!"
// will show "Bye!".
sayHello("Max",sayBye);
You are doing it wrong, you should do like bellow
Don't call the function just pass the function as callback
use this
sayHello("Max",saySeeYou); //here the second parameter is function
instead of
sayHello("Max",saySeeYou());//This will put the result of saySeeYou as second parameter
in say hello call the functiom
function sayHello(name,myfunc){
console.log("Hello");
myfunc();
}