Lets imagine that I have some code:
var someString = "";
function do1(){
doA();
doB();
}
function doA(){
// some process that takes time and gets me a value
someString = // the value I got in prior line
function doB(){
//do something with someString;
}
What is the correct way to make sure somestring is defined by doB tries to use it? I think this is a situation that calls for a callback, but I'm not sure how to set it up?
Usually, I have solved this problem like following code by callback parameter. However, I don't know this is correct answer. In my case, it's done well.
var someString = "";
function do1(){
doA(doB);
}
function doA(callback){
// some process that takes time and gets me a value
someString = // the value I got in prior line
callback();
}
function doB(){
//do something with someString;
}
I usually write these such that the function can be called with, or without, the callback function. You can do this by calling the callback function only if typeof callback === 'function'. This allows the function which includes the possibility of a callback to be a bit more general purpose. The call to the callback(), obviously, needs to be from within the callback of whatever asynchronous operation you are performing. In the example below, setTimeout is used as the asynchronous action.
var someString = "";
function do1() {
doA(doB); //Call doA with doB as a callback.
}
function doA(callback) {
setTimeout(function() {
//setTimeout is an example of some asynchronous process that takes time
//Change someString to a value which we "received" in this asynchronous call.
someString = 'Timeout expired';
//Do other processing that is normal for doA here.
//Call the callback function, if one was passed to this function
if (typeof callback === 'function') {
callback();
}
}, 2000);
}
function doB() {
//do something with someString;
console.log(someString);
}
do1();
You can, of course, do this without using a global variable:
function do1() {
doA(doB); //Call doA with doB as a callback.
}
function doA(callback) {
setTimeout(function() {
//setTimeout is an example of some asynchronous process that takes time
//Simulate a result
var result = 'Timeout expired';
//Do other processing that is normal for doA here.
//Call the callback function, if one was passed to this function
if (typeof callback === 'function') {
callback(result);
}
}, 2000);
}
function doB(result) {
console.log(result);
}
do1();
function someFunctionA(callback){
var someString = "modify me";
callback(someString);
}
function someFunctionB(someString){
// do something
}
function main() {
someFunctionA(somefunctionB);
}
Related
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)
}
I have 3 functions in my javascript code. I want to call the 3rd function as soon as both function1 and function2 are over executing.
func_one();
func_two();
func_three(); // To be called as soon both of the above functions finish executing.
Note that they may take variable time since function 1 and 2 are for fetching geolocation and some ajax request respectively.
How about this?
func_one() {
// Do something
func_two();
}
func_two() {
// Do something
func_three();
}
func_three() {
// Do something
}
There are two ways to solve this problem.The first one is to create callback functions as parameters for your existing functions.
function one(param_1 .. param_n, callback) {
var response = ... // some logic
if (typeof callback === "function") {
callback(response);
}
}
The second way is to use Promises like:
var p1 = new Promise(
function(resolve, reject) {
var response = ... //some logic
resolve(response);
}
}
var p2 = new Promise( ... );
p1.then(function(response1) {
p2.then(function(response2) {
//do some logic
})
})
You can try like this
var oneFinish = false;
var twoFinish = false;
function one(){
//...
oneFinish = true; // this value may depends on some logic
}
function two(){
//...
twoFinish = true; // this value may depends on some logic
}
function three(){
setInterval(function(){
if(oneFinish && twoFinish){
//...
}
}, 3000);
}
Since your functions func_one and func_two are making service calls you can call the functions on after other at the success callback of the previous function. Like
func_one().success(function(){
func_two().success(function(){
func_three();
});
});
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()
Please help in understanding the below code:
// define our function with the callback argument
function some_function(arg1, arg2, callback) {
// this generates a random number between
// arg1 and arg2
var my_number = Math.ceil(Math.random() * (arg1 - arg2) + arg2);
// then we're done, so we'll call the callback and
// pass our result
callback(my_number);
}
// call the function
some_function(5, 15, function(num) {
// this anonymous function will run when the
// callback is called
console.log("callback called! " + num);
});
In the above code,what is the callback keyword.what is the use of this word.
Even there is no function defined with name callback.
The gap in logic I think you're having a hard time with is anonymous, unnamed functions. Once upon a time, all functions were named. So code was written like this:
function MemberProcessingFunction() {
// etc
}
function AdminProcessingFunction() {
// etc
}
var loginProcessingFunction;
if (usertype == 'BasicMember') {
loginProcessingFunction = MemberProcessingFunction;
}
else if (usertype == 'Admin') {
loginProcessingFunction = AdminProcessingFunction;
}
loginProcessingFunction();
Someone thought "This is dumb. I'm only creating those function names to use them in one place in my code. Let's merge that together."
var loginProcessingFunction;
if (usertype == 'BasicMember') {
loginProcessingFunction = function() {
// etc
};
}
else if (usertype == 'Admin') {
loginProcessingFunction = function() {
// etc
};
}
loginProcessingFunction();
This especially saves a lot of time when you're passing a function to another function as an argument. Often, this is used for "callbacks" - occasions where you want to run certain code, but only after a certain indeterminately-timed function has finished its work.
For your top function, callback is the name of the third argument; it expects this to be a function, and it is provided when the method is called. It's not a language keyword - if you did a "find/replace all" of the word "callback" with "batmanvsuperman", it would still work.
'callback' is a function passed as an argument to the 'some_function' method. It is then called with the 'my_number' argument.
when 'some_function' is actually being called as seen below
// call the function
some_function(5, 15, function(num) {
// this anonymous function will run when the
// callback is called
console.log("callback called! " + num);
});
it receives the whole definition of the third function argument. so basically your 'callback' argument has this value below
function(num) {
// this anonymous function will run when the
// callback is called
console.log("callback called! " + num);
}
To understand better how a function can be passed as an argument to another function, take a look at this answer.
I'm using an anonymous function to perform some work on the html I get back using Restler's get function:
var some_function() {
var outer_var;
rest.get(url).on('complete', function(result, response) {
if (result instanceof Error) {
sys.puts('Error: ' + result.message);
} else {
var inner_var;
// do stuff on **result** to build **inner_var**
outer_var = inner_var;
}
});
return outer_var;
}
How can I get the value of inner_var out to the some_function scope and return it? What I have written here doesn't work.
The get call is asynchronous, it will take some time and call your callback later. However, after calling get, your script keeps executing and goes to the next instruction.
So here is what happens:
you call get
you return outer_var (which is still undefined)
... sometimes later ...
get result has arrived and the callback is called.
outer_var is set
You can't have your some_function return a value for something that is asynchronous, so you will have to use a callback instead and let your code call it once data is processed.
var some_function(callback) {
rest.get(url).on('complete', function(result, response) {
if (result instanceof Error) {
sys.puts('Error: ' + result.message);
} else {
var inner_var;
// do stuff on **result** to build **inner_var**
callback(inner_var);
}
});
}
Like most of the modules of node, Restler is also a event based library having async calls. So at the time you do return outer_var; the complete callback was not necessarily called (With some libraries it could be if it the result was cached, but you should always expect that it is called asynchronous).
You can see this behavior if you add some logging:
var some_function() {
var outer_var;
console.log("before registration of callback"); //<----------
rest.get(url).on('complete', function(result, response) {
console.log("callback is called"); //<----------
if (result instanceof Error) {
sys.puts('Error: ' + result.message);
} else {
var inner_var;
// do stuff on **result** to build **inner_var**
outer_var = inner_var;
}
});
console.log("after registration of callback"); //<----------
return outer_var;
}
So if you would like to do something with this value you would need to call the function that should do something with this value out of your complete callback.
Remove the var outer_var; from your function some_function;
Declare the var outer_var; upper then your function
It should be work after you did step 1, not really need step 2.