I've been reading about async functions in JavaScript and found out that I don't quite understand the following piece of code that comes from here.
Here it is:
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log('Got the final result: ' + finalResult);
}, failureCallback);
}, failureCallback);
}, failureCallback);
What I don't understand is where all these results come from.
They are callbacks. A callback is just simply a function which is passed as an argument to another function and is used to do something with the result of some operation done by the function which receives the callback as an argument. You can write your own. A simple example:
function callMe(callback) {
let addition = 2 + 2;
callback(addition);
}
callMe(function(result) {
console.log(result);
});
callMe calls its callback function with the result of 2 + 2. You then receive that result inside the callback function when you use callMe, and you can then write your own custom code to do whatever you want with it.
The beauty of JavaScript is that you already have all you need to test it.
The code you posted references 4 functions (don't forget the failure callback):
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log('Got the final result: ' + finalResult);
}, failureCallback);
}, failureCallback);
}, failureCallback);
Those functions are not written. So let's write them:
var failureCallback = function() {
console.log('something went wrong');
}
var doSomething = function(callback) {
window.setTimeout(function() {
var result = Date.now(); // Create some data that will change every time the function is invoked
callback(result);
}, 500);
}
var doSomethingElse = function(res, callback) {
window.setTimeout(function() {
var result = [res]; // all this function really does is put the first argument in an array
callback(result);
}, 500);
}
function doThirdThing(res, callback) {
window.setTimeout(function() {
res.push(Math.PI); // res is supposed to be an array, so we can add stuff to it.
var result = res;
callback(result); // here we could have used res as a value, but I kept it consistent
}, 500);
}
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log('Got the final result: ', finalResult); // switched to a comma to display properly in the console
}, failureCallback);
}, failureCallback);
}, failureCallback);
To create some asynchronicity I used setTimeout so overall you have to wait 1.5 seconds.
The 3 functions that use a callback function as an argument, simply execute the function they were given. This is absolutely standard in JavaScript where functions are first class objects: you can pass them around as arguments like any other value type.
Javascript is a single threaded language, callbacks are used as a way to control the flow of execution when a asynchronous block of code ends in a non-blocking way. A callback is normally just another function (function B) that is passed into the asynchronous function (function A) to run when function A completes. I.E
doSomething(func) {
// do async code.
// call func
// func()
}
you haven't posted the inner blocks of those functions but i think we can all safely assume "result" is the response from the server passed back into the callback function I.E
doSomething(callback) {
//fetch or ajax or whatever to server store response.
//pass response BACK to callback function
callback(response)
}
Related
I am beginner at javascript. I want to understand more Callback Function because i have spend a lot time to learning this function but i not yet understood clearly.
This is my code. i want to make new function(callback) to continue this code, and show all month using method map
const getmonth = (callback) => {
setTimeout(() => {
let error = true;
let month = ["January","February","March","April","Mey","Juny","July","August","September","October","November","Desember"];
if(!error) {
callback(null, month)
} else {
callback(new error("Data gak ketemu", []))
}
}, 4000)
}
Callback is the function, which is passed to another function as an argument.
For example:
function sayHello(callback) {
console.log('Hi everyone');
setTimeout(function(){
callback(); // execution your function with 3 seconds delay
}, 3000);
}
In your case(I'm not using arrow functions to make it more easy to understand for you):
// Lets create a function, which will just print month which is passed as an argument
const printMonth = function(month) {
console.log(month);
}
// Now we are using map function
// https://developer.mozilla.org/uk/docs/Web/JavaScript/Reference/Global_Objects/Array/map
month.map(function(month) {
console.log(month);
});
The map function accepts another function as an argument(it's called callback) and in this function you can do whatever you want with every single element of array. You can also use an return to return new array with modified elements of it.
callbacks are often used to continue code execution after an asynchronous operation has completed.
more about callback functions
You can create callback function on your code like this.
getmonth((err,data)=>{
if(!err){
data.map(month =>month);
}
return err;
})
I have trouble understanding how callbacks in JavaScript get their arguments. Or in other words: how to implement a higher-order function so its callback accepts for instance a standard err and data arguments.
Like in this article on asynchronous JavaScript in the example of a callback used in a usual way (and I know it's usual because I see exactly this pattern used in Node.js moongose (i.e. for creating data in db)):
function getData(options, callback) {
$.get("example.php", options, function(response) {
callback(null, JSON.parse(response));
}, function() {
callback(new Error("AJAX request failed!"));
});
}
// usage
getData({name: "John"}, function(err, data) {
if(err) {
console.log("Error! " + err.toString())
} else {
console.log(data);
}
});
how exactly the callback gets arguments err & data based on how getData() function is declared above?
Arguments are passed to a function when that function is called.
function foo(arg) {
console.log(arg);
}
foo("This is the value");
This is still true when it is a callback function.
function foo(arg) {
console.log(arg);
}
function bar(callback) {
callback("This is the value");
}
bar(foo);
And it is still true when the callback function is called by code written by someone else that exists in a library you aren't examining the source code of.
function firstFunction(_callback){
// do some asynchronous work
// and when the asynchronous stuff is complete
_callback();
}
function secondFunction(){
// call first function and pass in a callback function which
// first function runs when it has completed
firstFunction(function() {
console.log('huzzah, I\'m done!');
});
}
This is an example from this site, I would like help understanding it.
If I have a function that sums 2 number and the other returns it. So:
var z = 0;
function firstf (x, y, callback){
z = x + y;
callback();
}
function secondf () {
console.log(z);
}
I dont get how this works? How do I make it so that secondf waits until firstf is done using callbacks?
After define 2 function, you call:
firstf(2,3,secondf);
Follow : z=2+3 then call function callback. And now, function callback ~ secondf :
z=2+3 ;
secondf();
If you want to the second block to wait until the first block is done. Then using callback makes no sense.
Because the main concept of callback is to provide an asynchronous platform.
A callback is a function call at the completion of a given task, hence prevents any blocking which may might occur if the first block takes long time to load data.
So, if you want both the blocks to work asynchronously the use callback, and to achieve what you are asking simply call the second function after the task of block one is done.
For better understanding go through this link,
https://docs.nodejitsu.com/articles/getting-started/control-flow/what-are-callbacks/
Best of luck!
You can use "promise" concept to ensure that the secondf waits until firstf is done:
function firstf(x,y){
return new Promise(
function (resolve, reject) {
resolve(x+y);
});
}
function secondf(){
firstf(x,y).then ( function (result){
console.log(result);
});
}
By re-ordering your code:
edit Made code async for demo purposes
var z = 0;
function firstf(x, y, callback) {
console.log("Inside firstf");
z = x + y;
console.log("Will call callback in 1 second");
// Lets make this function async.
setTimeout(function() {
console.log("Calling callback");
callback();
}, 1000);
}
function secondf() {
console.log("Inside secondf");
console.log(z);
console.log("Leaving secondf");
}
firstf(1, 2, secondf);
I am new to javascript and I am trying to understand callbacks. I am not able to understand why 20 is getting printed before 10. My understanding is for a callback function like - func1(parameter,func2()) , func2() is the callback function, which gets executed after func1 executes with the "parameter" passed to func1. Is my understanding correct?
function timePass(length){
console.log("finished after doing timePass for "+length +" seconds")
}
timePass(10,timePass(20));
OUTPUT BELOW:
finished after doing timePass for 20 seconds
finished after doing timePass for 10 seconds
You are not really creating a callback function but actually calling timePass(20) before everything else on your last line of code.
To pass a callback function you should do something like this:
function timePass(length,callback){
console.log("finished after doing timePass for "+length +" seconds")
if(typeof(callback) == "function")
callback(20);
}
timePass(10,timePass);
This is because you execute the function timePass and then - adding the result as argument number 2.
Explaining what is happening:
First you define new function "timePass", The function printing on the console.
Second you execute timePass(10, /*But here you execute it again*/ timePass(20)).
The function timePass(20) will be executed first because you added ().
() == execute. If you just pass the name of the function, it will be passed as function. When you use () it will be executed and then the result will be passed as argument.
EXAMPLE OF USING CALLBACK
function timePass(length, callbackFunction){
console.log("finished after doing timePass for "+length +" seconds");
// check if the function caller is included callback parameter
// and check if it is function - to prevent errors.
if (callbackFunction && typeof callbackFunction == "function") {
// Execute the callback (timePass)
callbackFunction(20);
}
}
// Here you say, Execute timePass with arg 10, and then call timePass
timePass(10, timePass);
// and now callbackFunction defined above will be == timePass
// You can do also
timePass(10, anotherFunction)
// So another function will be executed after console.log()
USE CASES
Most often callbacks are used while we working with async code.
For example: Jsfiddle
// Imagine we have function which will request the server for some data.
function getData(index) {
// The request - response will took some time
// 0.1s ? 15s ? We don't know how big is the data we downloading.
var data;
// Imagine this is an AJAX call, not timeout.
setTimeout(function() {
// after 30ms we recieved 'server data'
data = 'server data';
},30)
return data;
}
var users = getData('users');
console.log(users); // undefined - because we returned "data" before the AJAX is completed.
/*
So we can change the function and adding an callback.
*/
function getAsyncData(index, callback) {
var data;
// Imagine this is an AJAX call, not timeout.
setTimeout(function() {
// after 30ms we recieved 'server data'
data = 'server data';
callback(data);
},30)
}
getAsyncData('users', function(data) {
console.log(data); // 'server data'
});
// OR
function processData(data) {
console.log(data);
}
getAsyncData('users', processData); // processData also logs 'server data'
basically when the interpreter is looking at this, it will call timepass(20) to evaluate the result (which is nothing as you have no return returning something), which then it tries to pass into the outer function.
i.e.
doFunction( doSomethingElse() );
if doSomethingElse returns 1, it must evaluate that before it can pass that 1 into doFunction.
Fundamentally, you have not actually passed a callback, you have called the function. Perhaps you meant:
callback = function() { somecode; }
target = function(data, callback) { console.log('hi'); callback(); }
target(10, callback);
notice the lack of () i.e. callback not callback()
I am new to node.js and came across this bit of code and am trying to understand what the word "callback" is doing. I mean I know what a callback is, but why are they actually using the word "callback" below and what is it doing. Really appreciate your help.
io.sockets.on('connection', function(socket) {
socket.on('nickname', function(data, callback) {
if (nicknames.indexOf(data) != -1) {
callback(false);
} else {
callback(true);
nicknames.push(data);
socket.nickname = data;
console.log('Nicknames are ' + nicknames);
}
});
});
It's a variable name.
It's defined in the function expression as an argument: function (data, callback) {.
The expectation is that the value passed to it will be a function (hence the function being called here: callback(false);).
For a simple example that doesn't depend on any library code you can't see:
function doSomething(callback) {
alert("doing something");
callback(1);
}
function myCallback(value) {
alert("myCallback called with the argument: " + value);
}
doSomething(myCallback);
But function (data, bob) is the callback function. Why include "callback" (or bob) within the callback. Does that make sense?
You have multiple callback functions.
One callback function is passed another function as an argument which it, in turn, calls.
Node.js uses asynchronous callback functions instead of blocking the caller and performing the operation synchronously. callback is simply the very common name given to the variable that holds the callback function. I usually name the variable done in my own code simply because it is shorter.
In Node.js, callback is the de-facto standard name for callback functions. You could easily call it bob, and it would have the same effect:
io.sockets.on('connection', function(socket) {
socket.on('nickname', function(data, bob) {
if (nicknames.indexOf(data) != -1) {
bob(false);
} else {
bob(true);
nicknames.push(data);
socket.nickname = data;
console.log('Nicknames are ' + nicknames);
}
});
});
As to what it's doing, think of it as an anonymous function that notifies the caller (like a parent function) that the called function is done. A simpler example would be:
Function A calls function B (which takes a long time to run). When B is done, it needs to tell A that it's done:
function a() {
b(someParameter, function(err, data) {
// function(err, data) is the anonymous function we pass as a parameter to b()
});
}
function b(someParemeter, callback) {
// do something that takes a while
// 'callback' is the variable name for the anonymous function that was passed
// We execute it using ():
callback(err, data);
}
Assuming that this is socket.io, that callback is used to respond to a client when the 'nickname' event is triggered.
From their documentation
Sending and getting data (acknowledgements)
Sometimes, you might want to get a callback when the client confirmed
the message reception.
To do this, simply pass a function as the last parameter of .send or
.emit. What’s more, when you use .emit, the acknowledgement is done by
you, which means you can also pass data along:
Server (app.js)
var io = require('socket.io')(80);
io.on('connection', function (socket) {
socket.on('ferret', function (name, fn) {
fn('woot');
});
});
Client (index.html)
<script>
var socket = io(); // TIP: io() with no args does auto-discovery
socket.on('connect', function () { // TIP: you can avoid listening on `connect` and listen on events directly too!
socket.emit('ferret', 'tobi', function (data) {
console.log(data); // data will be 'woot'
});
});
</script>