I was watching this talk on the event loop in JavaScript and it explained how "callbacks" are executed. And I wrote this to see how it works:
function show(str) {
return 'Hello ' + str;
}
// This does not work
show('World', function (data) {
console.log(data);
});
// This works
console.log(show('Sayantan'));
Maybe I got this whole thing wrong. But how do I pass callbacks as parameters like the way I tried to do. For example in jQuery's $.get() or $.post() where we give a callback to do what we want to do after the response came back. So I hoping the function call would print 'Hello World' in console as that's what I defined in my callback. What am I doing wrong?
You're almost there - the only thing you didn't do is handle the callback in show:
function show(str,callback) {
callback('Hello ' + str); // this will execute the anonymous function with 'Hello ' + `str` as the variable
return 'Hello ' + str;
}
You could take the callback and call it in the function show with the wanted parameter.
function show(str, cb) {
return cb('Hello ' + str);
}
show('World', function (data) {
console.log(data);
});
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've written a function which may take an unknown number of functions as parameters, but can't figure how I can make this work when one or more of the functions take parameters too.
Here is a quick example of what I would like to achieve:
function talk(name) {
console.log('My name is ' + name);
var callbacks = [].slice.call(arguments, 1);
callbacks.forEach(function(callback) {
callback();
});
}
function hello() {
console.log('Hello guys');
}
function weather(meteo) {
console.log('The weather is ' + meteo);
}
function goodbye() {
console.log('Goodbye');
}
// I would like to be able to do the following:
//talk('John', hello, weather('sunny'), goodbye);
You can pass an anonymous function which can call the function with required parameters
talk('John', hello, function(){
weather('sunny')
}, goodbye);
function talk(name) {
console.log('My name is ' + name);
var callbacks = [].slice.call(arguments, 1);
callbacks.forEach(function(callback) {
callback();
});
}
function hello() {
console.log('Hello guys');
}
function weather(meteo) {
console.log('The weather is ' + meteo);
}
function goodbye() {
console.log('Goodbye');
}
talk('John', hello, function() {
weather('sunny')
}, goodbye);
talk('John', hello, weather.bind(null, 'sunny'), goodbye);
In this case .bind is essentially returning a function with some bound parameters - quite analogous to Arun's answer, though you may consider this method a little more succinct / readable.
I have many services which gives data but takes time so is there a way to hold the control in angularJS or JQuery which will be executed once the other code will be finish.
Ex:
function fun1(){
// many functions get data
}
function fun2(){
// many functions get data
}
function fun3(){
// here I want to call fun1()
//once fun1() is executed then only call fun2()
}
Any idea how to achieve this in the angularJS?
Thanks in advance.
Callbacks would work:
function fun1(cb) {
// do stuff
cb();
}
function fun2() {
// do stuff
}
function fun3() {
fun1(fun2);
}
Or go with promises as outlined in the other answer.
You can use promises or $q
See here for more details https://docs.angularjs.org/api/ng/service/$q
function fun1(){
var deferred = $q.defer();
setTimeout(function() {
deferred.notify('About to greet ' + name + '.');
if (okToGreet(name)) {
deferred.resolve('Hello, ' + name + '!');
} else {
deferred.reject('Greeting ' + name + ' is not allowed.');
}
}, 1000);
return deferred.promise;
}
function fun2(){
// many functions get data
}
function fun3(){
// here I want to call fun1()
//once fun1() is executed then only call fun2()
var promise = fun1();
promise.then(function() {
//called if fun1 return successfully
fun2();
}, function(reason) {
alert('Failed: ' + reason);
}, function(update) {
alert('Got notification: ' + update);
});
}
You cannot stop the code flow in javascript using any framework out there. What you are refering to is async code flow Which as referred by folks below can be done by promises or callbacks only
I am learning AngularJS and have copied code this basic code from a tutorial (simplified/pseudo code to only include the parts relevant to this question).
The code works for me, but I am trying to better understand how the argument is being passed the the callback in the success method.
// jobService object
var jobService = {
get : function() {
return $http.get( 'some/api/url' );
}
};
jobService.get().success(function (data) {
$scope.jobs = data;
});
My question is, knowing that "normally" arguments are specifically passed into the functions when invoked i.e.:
function foo(arg1) {
alert(arg1); //alerts Hello!
};
foo('hello!');
How is the data argument being passed into the anonymous callback function?
is it:
Being "injected" by AngularJS?
Does the javascript engine simply use variables on the local scope called data?
does the javascript engine look for a data property on the parent object if the success method?
TL;DR
We're just defining that anonymous function, not calling it!
Thus data is a function parameter, not a function argument.
Long version
Let's take this into little pieces.
success() is a function. It's chain-called after jobService.get(). So, whatever the jobService.get() call returns, we're calling the success function of that object (say returnedObject.success()).
Back to success() itself. It can easily read other properties of its object (returnObject from the example above). Since we're passing in the anonymous callback function as an argument, success can easily do something like (narrowing it down to basic JS):
function success(callback) {
var whatever = "I'm passing this to the callback function";
callback(whatever);
}
which would actually call our anonymous function we passed in, and assign it whatever as data (don't forget we're just defining that anonymous function, not calling it!) . This makes data a function parameter, and it is basically a custom name that you use to represent and access what the success function passes into its callback function. You can use whatever you want there - this would still work perfectly fine:
jobService.get().success(function (somethingElse) {
$scope.jobs = somethingElse;
});
Hope I didn't make this too complicated. I was trying to explain it step-by-step from the plain JS standpoint because you can easily read Angular's source to see what it does, so I thought you needed this simpler explanation.
Here's a basic example replicating what's going on there (inspect the JS source, see how the output is the same in all three cases):
var debug = document.getElementById('debug');
function success(callback) {
var whatever = 'hello world';
debug.innerHTML += '<br>success function called, setting parameter to <span>' + whatever + '</span><br>';
callback(whatever);
}
function callbackFunction(someParameter) {
debug.innerHTML += '<br>callbackFunction called with parameter <span>' + someParameter + '</span><br>';
}
success(callbackFunction);
// anon function
success(function(val) {
debug.innerHTML += '<br>anonymous callback function called with parameter <span>' + val + '</span><br>';
})
// anon function 2
success(function(anotherVal) {
debug.innerHTML += '<br>second anonymous callback function called with parameter <span>' + anotherVal + '</span><br>';
})
span {
color: green;
}
<div id="debug"></div>
An example using an object, similar to what is done in your original code:
var debug = document.getElementById('debug');
var myObject = {
whatever: 'hello world',
success: function(callback) {
debug.innerHTML += '<br>success function called, fetching object property and setting the parameter to <span>' + this.whatever + '</span><br>';
callback(this.whatever);
},
modifyMe: function() {
debug.innerHTML += '<br>object property modified<br>';
this.whatever = 'another world';
return this; // this is crucial for chaining
}
}
// anon function callback
myObject.success(function(val) {
debug.innerHTML += '<br>anonymous callback function called with parameter <span>' + val + '</span><br>';
})
debug.innerHTML += '<br><hr>';
// chaining - calling a success function on a modified object
myObject.modifyMe().success(function(val) {
debug.innerHTML += '<br>anonymous callback function called with modified parameter <span>' + val + '</span><br>';
})
span {
color: green;
}
<div id="debug"></div>
Here's the relevant part in the source code:
promise.success = function(fn) {
promise.then(function(response) {
fn(response.data, response.status, response.headers, config);
});
return promise;
};
Read more on GITHUB.
I was wondering which is the way to make this simple (and maybe stupid) thing with jQuery.
I have a function like this:
function setSomething() {
make some stuff;
}
and then another function like this:
generalFunction(par1, par2, par3) {
do other stuff;
execute function called in par3;
}
Well, if I write something like this it doesn't work:
c=setSomething();
generalFunction(a, b, c);
So what's the way to call a function as a parameter of another function and then execute it inside?
I hope I was clear enough.
Any help will be appreciated.
Thank you in advance for your attention.
leave out the parentheses , you can then call the parameter as a function inside your "generalFunction" function.
setSomething(){
// do other stuff
}
generalFunction(par1, par2, par3) {
// do stuff...
// you can call the argument as if it where a function ( because it is !)
par3();
}
generalFunction(a, b, setSomething);
Here is another example for those who want to pass a parameter to a function that is passed in as a call back:
$(document).ready(function() {
main();
});
function main() {
alert('This is the main function');
firstCallBack(1, 2, 3, secondCallBack);
};
function firstCallBack(first, second, third, fourth) {
alert('1st call back.');
var dataToPass = first + ' | ' + second;
fourth(dataToPass);
};
function secondCallBack(data) {
alert('2nd call back - Here is the data: ' + data)
};
Here is the JSFiddle link: https://fiddle.jshell.net/8npxzycm/