How to properly use JavaScript callback without jquery - javascript

I have been using jquery and javascript for a long time. I have rarely ever written javascript without jquery, and this instance requires me understand callbacks with javascript. Its a simple case, but I don't understand how it works. Not only do I want to get it working, I want to understand the callback.
const ALL_DATES = ["05/01/1992", "01/01/2017", "09/17/2010", "07/07/2017", "07/17/2017", "09/23/2013", "03/30/2012";
//console.log(ALL_DATES);
function filterDates(input) {
// Do your filtering here and use ALL_Dates
return input;
}
export function getDates(input, cb) {
setTimeout(() => {
cb(filterDates(input));
}, 300);
};
First I create fake data in the constant: ALL_DATES. filterDates function will be used to do filtering to my specific criteria.
What I don't fully grasp is the usage of getDates function (in the case, this function has to be utilized) and what I will be using for the callback function. In jquery, for example, what I would do is use the .change to check for a change event on an input, and run the getDates function again.
Can someone please help me grasp and understand the usage of the callback here, and what purpose it has to serve?
Thank you!

"What I don't fully grasp is the usage of getDates function (in the case, this function has to be utilized) and what I will be using for the callback function..."
The callback function will be whatever desires to receive the filtered dates. So whatever code calls getDates will presumably want to do something with the dates, and so will pass a callback that expects to receive those dates.
// Userland code
getDates(function(dates) {
// User now gets to work with the list of dates that you filtered internally
dates.forEach(d => console.log("The date is %s", d));
})
However, if there's nothing asynchronous going on, you could just have getDates() return the dates instead of receiving a callback function. In your case, the setTimeout provides async behavior, but barring any sort of async processing like that, you'd more likely just return them.

If you take out the node and the jQuery - and try and build a simplified version - you may have a quicker time to grok it. Maybe these will help. A callback is just a function passed to another function. 'higher order function' is a confusing way of marketing it. jQuery methods often have an optional 'callback' /anonymous function that can run AFTER whatever that method does is done. The syntax is something you get used to - but it fogs up the view... if you aren't aware of the methods arguments and true nature.
$(document).ready( function() {
console.log('DOM ready');
});
// vs
function sayReady() {
console.log('DOM ready again...');
}
$(document).ready(sayReady);
examples: https://jsfiddle.net/sheriffderek/b6jj5z2u/
For the most part now though... async stuff is much easier to reason about with promises or async/await techniques... say you get data from an API, and you don't want to try and 'do' anything with it until it is all there / callbacks are pretty tough to write all the logic for - comparatively.
console.clear();
var exampleArray = [2, 45, 63, 7, 9, 12];
function doubleInput(number) {
return number * 2;
}
function iterateOverArray(array) {
console.log('iterateOverArray');
for (var i = 0; i < array.length; i++) {
console.log('-', array[i] );
}
return true;
// you should really be returning something...
}
iterateOverArray(exampleArray);
// this function accepts an array and a function to run on each item
// not far off from array.forEach()...
function iterateAndRunFunction(array, exampleCallback) {
console.log('iterateAndRunFunction');
var newArray = [];
for (var i = 0; i < array.length; i++ ) {
var manipulatedValue = exampleCallback( array[i] );
newArray.push(manipulatedValue);
}
console.log(newArray);
return newArray;
// you should really be returning something...
}
iterateAndRunFunction(exampleArray, doubleInput);
function saySomething(message) {
console.log(message);
}
function doSomethingLater(functionToRun, waitTime) {
console.log('wait ' + waitTime + 'ms');
setTimeout( function() {
saySomething('HI!!! sorry I took ' + waitTime + 'ms');
}, waitTime);
}
doSomethingLater(saySomething, 3000);

A callback is a reference to a function (function A) that you hand over to another function (function B) so that function B can call function A when it decides to. Check this out:
const FIVE_MINS = 300000
const rightNow = new Date()
function getTime(startTime) {
if (typeof startTime === 'undefined') startTime = new Date()
alert(startTime.getHours() + ":" + startTime.getMinutes() + ":" + startTime.getSeconds())
}
getTime() is a function that alerts the user to the time that is passed to it as an argument, or if it receives no argument, the time at the moment it is called.
setTimeout() wants a function as its first argument so it can call that function in 5 minutes. If you were to do this:
setTimeout(getTime(), FIVE_MINS)
you would see the alert immediately because getTime() IS BEING CALLED in this expression. Don't do that. setTimeout() is expecting a function reference so that it can call getTime() itself when the time comes. There is two ways to reference a function.
If the function needs no arguments, you can just pass the name without the parens. That is a reference to a function and the function can be dealt with later.
setTimeout(getTime, FIVE_MINS)
Notice getTime() doesn't have an argument, so it is going to use whatever "now" is at the time setTimeout() calls it (5 mins from now). If your function needs arguments, you can reference the function in this way:
setTimeout(() => getTime(rightNow), FIVE_MINS)
In this case, I am passing in rightNow which is the datetime of when this file first started being parsed. So no matter how long setTimeout() waits, when it calls getTime() it will alert the user to the time it was when setTimeout started, pretty much.
Couple last things I'll mention is that this older syntax is equivalent to the example above:
setTimeout(function() {getTime(rightNow)}, FIVE_MINS)
You'd have to use the older syntax if you don't have a transpiler like Babel in your project to translate ES6 (new JS syntax).
And one last, last thing I'll mention, which is the most complex thing about callbacks, is that they can be called with arguments from within the function they have been handed over to, and you can intercept/add to/alter these arguments from the outer function before they get passed to the inner one if you need to. But I'd have to set up a much more complex example to show you that and I think your question only relates to the basic use of callbacks.

Related

Binding an argument to a function in javascript [duplicate]

I'm really new to JS and I'm having a lot of trouble writing/understanding callback functions
Let's say for example, I have the following code, but i dont want
takeNumbersGreaterThan(5);
to be executed until
insertNumbers();
is finished
numbers = [];
greaterThan = [];
insertNumbers();
takeNumbersGreaterThan(5);
insertNumbers(){
for (var i = 0; i<11; i++)
{
numbers.push(i)
}
}
takeNumbersGreaterThan(number){
for (var m = 0; m<numbers.length; m++)
{
if (numbers[m] > number)
{
greaterThan.push(numbers[m])
}
}
}
How do I go about doing that?
The basics (not about callbacks, but about programming languages)
To understand callbacks first you have to understand functions. And to understand functions in javascript you first have to understand variables, values and functions.
Almost all programming language can deal with values. So if you've done any programming you'd have a basic idea of what values are (I'm going to greatly simplify types of values here and refer to both values and references/pointers as "values").
A value is a thing. For example a number or a string. So 22.31 is a value and "Hello Dave" is a value.
Most languages also have the concept of variables (not all do though). A variable is a "name" we give to values to make it easier to process values. For example, in the following, x is a variable:
var x = 12;
.. and it's value is 12.
What do variables allow us to do? It allows us to substitute a value for a name in our calculations. Just like math. For example, if x is 12 and we know we can add 1 to 12 we can also do:
x + 1
Functions are values
In javascript functions are values. For example, in the following we assign a function to a variable:
function a () {return "Hello"}
var y = a;
Since what variables do is to allow you to substitute a name for a value then if you can call the function a using the syntax a() it means you can also do this with the variable y:
y(); // returns "Hello"
Callbacks
If functions are values it also means that you can pass functions as arguments to other functions. For example, the following is how you'd normally call a function in another function:
function a () {return "Hello"}
function b () {return a() + " World"}
b(); // returns "Hello World"
If you can pass functions as a variable, it means you can do something like this:
function a () {return "Hello"}
function b () {return "Bye"}
function c (functionVariable) {return functionVariable() + " World"}
c(a); // returns "Hello World"
c(b); // returns "Bye World"
As you can see. Callbacks are not special at all. They're just the result of the fact that in javascript functions obey the same rules as other values like numbers, arrays and strings.
Callbacks does not mean asynchronous
As you can see from the example above, both calls to the function c return a value. Thus the function c is not asynchronous even though it accepts a callback. So callbacks can be used for both synchronous and asynchronous code.
A good example of a synchronous callback is the Array.sort() method. It sorts an array but accepts an optional callback for you to define how to sort (alphabetically, numerically, by last name etc.).
Why asynchronous code need callbacks
For now forget about ajax or networking code. Let's instead look at a scenario that makes it even more obvious why callbacks are used by asynchronous code.
Say for example you have a button. Now, when the user click this button you want something to happen. How do you do that?
The first thing most people do is probably something like this:
while (1) {
if (button.isClicked) {
doSomething();
}
}
OK. So that's an infinite loop that only checks if the button is clicked and nothing else. Then how do you expect the browser to update the UI and track the mouse? This leads us to the next thing people try to do:
while (1) {
if (button.isClicked) {
doSomething();
}
else {
updateUI();
}
}
OK. Great. But two problems. First, if someone were to write a library like Google Charts or jQuery or anything to do with the UI they either will write their own while(1)... loop or you must manually copy/paste their function into your while loop. This does not scale. Second and more importantly, this is inefficient. That while loop will use 100% CPU time checking a button. Wouldn't it be nicer if the browser can tell us when the button is clicked.
Fortunately in javascript functions are just values. You can pass a function to the browser and tell it to execute your function when someone clicks a button:
button.addEventListener('click', doSomething);
Note: Notice the difference between treating a function as a variable and calling a function. If you want to treat a function as a variable just use the name. If you want to call a function use braces like doSomething().
Why everyone insist on writing asynchronous functions
There are two reasons why everyone seem to insist on making asynchronous APIs, especially in languages like javascript.
First, the low-level file and network I/O are async. This means that if you want to talk to a database or a server or read a file you need to implement it as asynchronous. Also, javascript is single threaded. So if you use the synchronous versions of I/O functions you will freeze everything else.
Second, it turns out that in a lot of cases (but certainly not in all) asynchronous, single-threaded programming is as fast as or sometimes even faster than synchronous multi-threaded programming.
Combined, the two reasons above creates social pressure in the js community to ensure that all I/O code are asynchronous in order to maintain the speed advantage and not block other people's code.
If I understand correctly, you want to know more about callbacks and you want to use them. Let me try too help you using your code.
If you want to execute takeNumbersGreaterThan(5); right after insertNumbers(); using callback function, you could do something like this:
numbers = [];
greaterThan = [];
insertNumbers(takeNumbersGreaterThan, 5);
function insertNumbers(callbackFunction, callbackFunctionParam){
for (var i = 0; i<11; i++)
{
numbers.push(i)
}
callbackFunction(callbackFunctionParam);
}
function takeNumbersGreaterThan(number){
for (var m = 0; m<numbers.length; m++)
{
if (numbers[m] > number)
{
greaterThan.push(numbers[m])
}
}
}
but this is just a simple example of how you can call a callback function after some computation. This code could be improved. The point is, you can pass your callback function as parameter on your function and then later execute this callback function.
You are already there. Your code is almost completely correct.
You was just missing function keywork declaration.
The script below, shows you how to run takeNumbersGreaterThan after insertNumbers. In my sample I also changed the function sign in order to pass array as parameters and avoid some of one common "mistakes" known as closures.
var numbers = [];
var greaterThan = [];
var insertNumbers = function(numbers) {
for (var i = 0; i<11; i++)
numbers.push(i)
}
var takeNumbersGreaterThan = function(number, numbers, greaterThan){
for (var m = 0; m<numbers.length; m++) {
if (numbers[m] > number)
greaterThan.push(numbers[m]);
}
}
// run insert numbers
insertNumbers(numbers);
// run take numbers greater than
takeNumbersGreaterThan(5, numbers, greaterThan);
// log
document.write(greaterThan);
Your code dosen't use any asyncronous calls so you wouldent need to use any callbacks to handle the execution. But if you would like to know how to do it, this would be the way.
numbers = [];
greaterThan = [];
function insertNumbers(callback){
for (var i = 0; i<11; i++)
{
numbers.push(i)
}
callback(); // now execute the callback funtion
}
function takeNumbersGreaterThan(number){
for (var m = 0; m<numbers.length; m++)
{
if (numbers[m] > number)
{
greaterThan.push(numbers[m]);
}
}
console.log(greaterThan);
}
insertNumbers(function() { // here we send a functions as argument to insertNumbers which will execute when callback() is called
takeNumbersGreaterThan(5);
});
insertNumbers takes a argument called "callback". When insertNumbers is finished we simply run callback(). In the initial call to insertNumber we pass a function as argument which will be executed as soon as insertNumers finished (or callback() is called).
Code (for the most part) is executed sequentially. In the code you've provided, the computer runs though the code in the order you've provided it. First it creates a new array object and sets it to the numbers variable, then it creates a new array object and sets it to the greaterThan variable.
Then, it runs the insertNumbers function. Now what the computer does is jump to the code that you've defined in insertNumbers and executes all that code. Then, after it finishes with that, it'll return to executing the initial thread of code it was on which is back at line 4. So now it'll jump to the takeNumbersGreaterThan code. So functionally, you don't need any callbacks since your code doesn't do anything that takes an arbitrary amount of time.
That being explained, you see that takeNumbersGreaterThan doesn't get executed until after insertNumbers is executed.
The only time code isn't executed sequentially is when you start doing multi core/threaded code.
Callbacks are used when something takes an arbitrary amount of time like when you are reading data from a disk or are requesting data from the network.
Callbacks can exist, because functions defined in javascript (and many other langauges) exist as objects in the code. If you don't put the parentheses after a function name, you're actually referencing the function object just like any other variable. So you can pass that function object around in your code and to other bits of code. That is what is happening in this example.
setTimeout(myCallback, 5000)
function myCallback(){
console.log("5 seconds have passed");
}
So, as you can see, I can take my function myCallback and give it to another function, in this instance setTimeout, to use after the other function has completed a task.

JS: What are the args in a debounce function

I am trying to grasp a debounce function in an existing codebase I am working on but I have a question that I can't understand while looking at it. What is (...args) in this scenario? I know it's a rest parameter but where did it come from and what is the purpose of args here? Why can't that just be empty and then called like fn() in the setTimout?
const debounce = (fn, delay) => {
let id;
return function(...args) {
if (id) {
clearTimeout(id)
}
id = setTimeout(() => {
fn(...args);
}, delay);
}
}
The function being returned from debounce() is supposed to act exactly the same as the function being provided, except for the fact that we're limiting how often it gets called. This means that if the original function was supposed to take two parameters, the returned function should too. That's why spread is being used.
As a simpler example, lets consider a wrapper function that just adds 1 to whatever gets returned.
function alsoAdd1(fn) {
return function(...args) {
return fn(...args) + 1
}
}
To use it, we can do the following:
> multiplyAndAdd1 = alsoAdd1(function(x, y) { return x * y })
> multiplyAndAdd1(2, 3)
7
> doubleAndAdd1 = alsoAdd1(function(x) { return x * 2 })
> doubleAndAdd1(2)
5
Notice how it doesn't matter how many parameters we pass into the wrapped function (like doubleAndAdd1), they're all get passed along to the original function (the double function). This is because we're using the spread operator.
If we look at the definition of alsoAdd1, we see that it'll give back a function that takes an arbitrary number of arguments, and passes all the arguments it receives into the function its wrapping.
The debounce() function is doing exactly the same thing, there's just a little bit more going on. These wrapper functions can be a little tricky to wrap your head around, so try going through those above examples slowly and see if you can grasp what they're doing.

Passing function as parameter on javascript

I recently started to learn javascript and saw this code. It was very different than C++ so please tell me what it means.
function getWeather(lat, lng){
fetch(
`https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lng}&appid=${API_KEY}&units=metric`
)
.then(function(response){
return response.json();
})
.then(function(json){
const temp = json.main.temp;
const place = json.name;
weather.innerText = `${temp} # ${place}`;
});
}
so basically it gets api and fetch it. After that it continues with .then(function(response)
I have no idea where that response come from. I can guess that response part is something returned from fetch function but still I don't understand how that happens.
const parsedToDos = JSON.parse(loadedToDos);
//for each takes function and execute function on each items.
parsedToDos.forEach(function(toDo){
paintToDo(toDo.text);
});
similar to the previous example, it takes toDo as parameter and it is not even global or local variable in this code but still used. Can anyone tell me the logic behind this?
Which arguments a function receivedsis determined by the caller of the function. If you have the following function
function add(a, b) {
return a + b;
}
Then "you" can call it as
add(1, 3)
Sometimes it is not directly "you" who calls the function, but another function. E.g.
function add1(a) {
return add(a, 1);
}
here add is called by add1. add1 will always pass 1 as second argument.
In addition to that, sometimes functions accept other functions as arguments and call them at some point. Again an example:
function doSomething(callback) {
return callback(40, 2);
}
Here doSomething accepts a function as argument and will always pass 40 and 2 as arguments. If I pass a function that expects to be passed two numbers it will work as expected:
// Works
doSomething(function (a, b) { return a + b; });
If I don't not, then I get some unexpected behavior or an error:
// Error :(
doSomething(function (a, b) { a.foo.bar = b });
But if that happens then I haven't read the documentation properly, because functions which accept callbacks usually explain which arguments are passed to the callback. For example for forEach (emphasis mine):
forEach() calls a provided callback function once for each element in an array in ascending order. It is not invoked for index properties that have been deleted or are uninitialized (i.e. on sparse arrays, see example below).
callback is invoked with three arguments:
the value of the element
the index of the element
the Array object being traversed
Similar for .then.
In summary, arguments are provided by the caller. If you pass a callback to a function then that function will most likely be caller and pass arguments. Read the documentation or look at the source code to find out which arguments these are.

setTimeout in javaScript not Working correctly

I know there is an Answer for this But!! All The Answers covered with only one setTimeout in the loop this Question Looks relevant to me How do I add a delay in a JavaScript loop?
But in my Scenario I Have two setTimeout in the Script, How can this be implemented correctly with timing !! The Program works correctly but the timing what I want is not correct !!!
function clickDate(i)
{
setTimeout((function(){
alert("4");
})(),2000);
}
function clickButton(i)
{
setTimeout((function(){
alert("5");
})(),4000);
}
function doEverything(i)
{
clickDate(i);
clickButton(i);
}
for(var i = 0; i < 4; i++)
{
doEverything(i);
}
You're immediately calling the function when you pass it to setTImeout. Remove the extra parenthesis.
function clickDate(i)
{
setTimeout(function(){
alert("4");
},2000);
}
function clickButton(i)
{
setTimeout(function(){
alert("5");
},4000);
}
function doEverything(i)
{
clickDate(i);
clickButton(i);
}
for(var i = 0; i < 4; i++)
{
doEverything(i);
}
EDIT
It's a little unclear what exactly it is you want your code to do seeing as you're passing i into your function I assume you want to use it somehow. Currently you're creating timeouts that will all launch at once. You'll need to stagger the delay times if you want them to launch in sequence. The code below logs a "4" every 2 seconds and a "5" every "4" seconds by multiplying the delay time by i+1.
// Currently this code displays a 4 every 2 seconds and a 5 every 4 seconds
function clickDate(i)
{
setTimeout(function(){
console.log("4");
},2000 * (i+1));
}
function clickButton(i)
{
setTimeout(function(){
console.log("5");
},4000 * (i+1));
}
function doEverything(i)
{
clickDate(i);
clickButton(i);
}
for(var i = 0; i < 4; i++)
{
doEverything(i);
}
Hello I think you havent read documentation about javascript.
It's asynchronous and it will not wait for the event and continue the process. I will give the answer but I highly recommend to read about Javascript it's good for you only here you will get timing problem because your both the function will be called at the same time. Let me give you the example.
function clickDate(i,callback)
{
setTimeout(function(){
alert("4");
callback();//this will call anonymous function in doEverything
},2000);
}
function clickButton(i)
{
setTimeout(function(){
alert("5");
},4000);
}
function doEverything(i)
{
console.log("In loop index is " , i);
clickDate(i,function(){
clickButton(i);
});
//look closely here I have passed the function in changeData and will call that funtion from clickDate
console.log("In loop terminating index is " , i);
}
for(var i = 0; i < 4; i++)
{
doEverything(i);
}
So here console log will make you clear about asynchronous
functionality. You will see that for loop terminates as it continues
it's work and easily completed in 2 seconds so before your first alert
for loop will complete it's iteration.
Hopefully this will help.
you are calling the callback immediately by adding () to the end of function .
you need to pass the callback with timeout and it will be call for you
setTimeout(function(){
alert('hello');
} , 3000);
function functionName() {
setTimeout(function(){ //Your Code }, 3000);
}
Try this one.
Your approach to mocking asynchronous behavior in JavaScript with setTimeout is a relatively common practice. However, providing each function with its own invocation of setTimeout is an anti-pattern that is working against you simply due to the asynchronous nature of JavaScript itself. setTimeout may seem like it's forcing JS to behave in a synchronous way, thus producing the 4 4 4 4 then 5 5 you are seeing on alert with iteration of the for loop. In reality, JS is still behaving asynchronously, but because you've invoked multiple setTimeout instances with callbacks that are defined as anonymous functions and scoped within their own respective function as an enclosure; you are encapsulating control of JS async behavior away from yourself which is forcing the setTimeout's to run in a strictly synchronous manner.
As an alternative approach to dealing with callback's when using setTimeout, first create a method that provides the timing delay you want to occur. Example:
// timer gives us an empty named "placeholder" we can use later
// to reference the setTimeout instance. This is important because
// remember, JS is async. As such, setTimeout can still have methods
// conditionally set to work against it.
let timer
// "delayHandler", defined below, is a function expression which when
// invoked, sets the setTimeout function to the empty "timer" variable
// we defined previously. Setting the callback function as the function
// expression used to encapsulate setTimeout provides extendable control
// for us later on however we may need it. The "n" argument isn't necessary,
// but does provide a nice way in which to set the delay time programmatically
// rather than hard-coding the delay in ms directly in the setTimeout function
// itself.
const delayHandler = n => timer = setTimeout(delayHandler, n)
Then, define the methods intended as handlers for events. As a side-note, to help keep your JS code from getting messy quickly, wrap your event handler methods within one primary parent function. One (old school) way to do this would be to utilize the JS Revealing Module Pattern. Example:
const ParentFunc = step => {
// "Private" function expression for click button event handler.
// Takes only one argument, "step", a.k.a the index
// value provided later in our for loop. Since we want "clickButton"
// to act as the callback to "clickDate", we add the "delayHandler"
// method we created previously in this function expression.
// Doing so ensures that during the for loop, "clickDate" is invoked
// when after, internally, the "clickButton" method is fired as a
// callback. This process of "Bubbling" up from our callback to the parent
// function ensures the desired timing invocation of our "delayHandler"
// method. It's important to note that even though we are getting lost
// in a bit of "callback hell" here, because we globally referenced
// "delayHandler" to the empty "timer" variable we still have control
// over its conditional async behavior.
const clickButton = step => {
console.log(step)
delayHandler(8000)
}
// "Private" function expression for click date event handler
// that takes two arguments. The first is "step", a.k.a the index
// value provided later in our for loop. The second is "cb", a.k.a
// a reference to the function expression we defined above as the
// button click event handler method.
const clickDate = (step, cb) => {
console.log(step)
cb(delayHandler(8000))
}
// Return our "Private" methods as the default public return value
// of "ParentFunc"
return clickDate(step, clickButton(step))
}
Finally, create the for loop. Within the loop, invoke "ParentFunc". This starts the setTimeout instance and will run each time the loop is run. Example:
for(let i = 0; i < 4; i++) {
// Within the for loop, wrap "ParentFunc" in the conditional logic desired
// to stop the setTimeOut function from running further. i.e. if "i" is
// greater than or equal to 2. The time in ms the setTimeOut was set to run
// for will no longer hold true so long as the conditional we want defined
// ever returns true. To stop the setTimeOut method correctly, use the
// "clearTimeout" method; passing in "timer", a.k.a our variable reference
// to the setTimeOut instance, as the single argument needed to do so.
// Thus utilizing JavaScript's inherit async behavior in a "pseudo"
// synchronous way.
if(i >= 2) clearTimeout(timer)
ParentFunc(i)
}
As a final note, though instantiating setTimeOut is common practice in mocking asynchronous behavior, when dealing with initial invocation/execution and all subsequent lifecycle timing of the methods intended to act as the event handlers, defer to utilizing Promises. Using Promises to resolve your event handlers ensures the timing of method(s) execution is relative to the scenario in which they are invoked and is not restricted to the rigid timing behavior defined in something like the "setTimeOut" approach.

JavaScript: How does a callback function work?

I'm really new to JS and I'm having a lot of trouble writing/understanding callback functions
Let's say for example, I have the following code, but i dont want
takeNumbersGreaterThan(5);
to be executed until
insertNumbers();
is finished
numbers = [];
greaterThan = [];
insertNumbers();
takeNumbersGreaterThan(5);
insertNumbers(){
for (var i = 0; i<11; i++)
{
numbers.push(i)
}
}
takeNumbersGreaterThan(number){
for (var m = 0; m<numbers.length; m++)
{
if (numbers[m] > number)
{
greaterThan.push(numbers[m])
}
}
}
How do I go about doing that?
The basics (not about callbacks, but about programming languages)
To understand callbacks first you have to understand functions. And to understand functions in javascript you first have to understand variables, values and functions.
Almost all programming language can deal with values. So if you've done any programming you'd have a basic idea of what values are (I'm going to greatly simplify types of values here and refer to both values and references/pointers as "values").
A value is a thing. For example a number or a string. So 22.31 is a value and "Hello Dave" is a value.
Most languages also have the concept of variables (not all do though). A variable is a "name" we give to values to make it easier to process values. For example, in the following, x is a variable:
var x = 12;
.. and it's value is 12.
What do variables allow us to do? It allows us to substitute a value for a name in our calculations. Just like math. For example, if x is 12 and we know we can add 1 to 12 we can also do:
x + 1
Functions are values
In javascript functions are values. For example, in the following we assign a function to a variable:
function a () {return "Hello"}
var y = a;
Since what variables do is to allow you to substitute a name for a value then if you can call the function a using the syntax a() it means you can also do this with the variable y:
y(); // returns "Hello"
Callbacks
If functions are values it also means that you can pass functions as arguments to other functions. For example, the following is how you'd normally call a function in another function:
function a () {return "Hello"}
function b () {return a() + " World"}
b(); // returns "Hello World"
If you can pass functions as a variable, it means you can do something like this:
function a () {return "Hello"}
function b () {return "Bye"}
function c (functionVariable) {return functionVariable() + " World"}
c(a); // returns "Hello World"
c(b); // returns "Bye World"
As you can see. Callbacks are not special at all. They're just the result of the fact that in javascript functions obey the same rules as other values like numbers, arrays and strings.
Callbacks does not mean asynchronous
As you can see from the example above, both calls to the function c return a value. Thus the function c is not asynchronous even though it accepts a callback. So callbacks can be used for both synchronous and asynchronous code.
A good example of a synchronous callback is the Array.sort() method. It sorts an array but accepts an optional callback for you to define how to sort (alphabetically, numerically, by last name etc.).
Why asynchronous code need callbacks
For now forget about ajax or networking code. Let's instead look at a scenario that makes it even more obvious why callbacks are used by asynchronous code.
Say for example you have a button. Now, when the user click this button you want something to happen. How do you do that?
The first thing most people do is probably something like this:
while (1) {
if (button.isClicked) {
doSomething();
}
}
OK. So that's an infinite loop that only checks if the button is clicked and nothing else. Then how do you expect the browser to update the UI and track the mouse? This leads us to the next thing people try to do:
while (1) {
if (button.isClicked) {
doSomething();
}
else {
updateUI();
}
}
OK. Great. But two problems. First, if someone were to write a library like Google Charts or jQuery or anything to do with the UI they either will write their own while(1)... loop or you must manually copy/paste their function into your while loop. This does not scale. Second and more importantly, this is inefficient. That while loop will use 100% CPU time checking a button. Wouldn't it be nicer if the browser can tell us when the button is clicked.
Fortunately in javascript functions are just values. You can pass a function to the browser and tell it to execute your function when someone clicks a button:
button.addEventListener('click', doSomething);
Note: Notice the difference between treating a function as a variable and calling a function. If you want to treat a function as a variable just use the name. If you want to call a function use braces like doSomething().
Why everyone insist on writing asynchronous functions
There are two reasons why everyone seem to insist on making asynchronous APIs, especially in languages like javascript.
First, the low-level file and network I/O are async. This means that if you want to talk to a database or a server or read a file you need to implement it as asynchronous. Also, javascript is single threaded. So if you use the synchronous versions of I/O functions you will freeze everything else.
Second, it turns out that in a lot of cases (but certainly not in all) asynchronous, single-threaded programming is as fast as or sometimes even faster than synchronous multi-threaded programming.
Combined, the two reasons above creates social pressure in the js community to ensure that all I/O code are asynchronous in order to maintain the speed advantage and not block other people's code.
If I understand correctly, you want to know more about callbacks and you want to use them. Let me try too help you using your code.
If you want to execute takeNumbersGreaterThan(5); right after insertNumbers(); using callback function, you could do something like this:
numbers = [];
greaterThan = [];
insertNumbers(takeNumbersGreaterThan, 5);
function insertNumbers(callbackFunction, callbackFunctionParam){
for (var i = 0; i<11; i++)
{
numbers.push(i)
}
callbackFunction(callbackFunctionParam);
}
function takeNumbersGreaterThan(number){
for (var m = 0; m<numbers.length; m++)
{
if (numbers[m] > number)
{
greaterThan.push(numbers[m])
}
}
}
but this is just a simple example of how you can call a callback function after some computation. This code could be improved. The point is, you can pass your callback function as parameter on your function and then later execute this callback function.
You are already there. Your code is almost completely correct.
You was just missing function keywork declaration.
The script below, shows you how to run takeNumbersGreaterThan after insertNumbers. In my sample I also changed the function sign in order to pass array as parameters and avoid some of one common "mistakes" known as closures.
var numbers = [];
var greaterThan = [];
var insertNumbers = function(numbers) {
for (var i = 0; i<11; i++)
numbers.push(i)
}
var takeNumbersGreaterThan = function(number, numbers, greaterThan){
for (var m = 0; m<numbers.length; m++) {
if (numbers[m] > number)
greaterThan.push(numbers[m]);
}
}
// run insert numbers
insertNumbers(numbers);
// run take numbers greater than
takeNumbersGreaterThan(5, numbers, greaterThan);
// log
document.write(greaterThan);
Your code dosen't use any asyncronous calls so you wouldent need to use any callbacks to handle the execution. But if you would like to know how to do it, this would be the way.
numbers = [];
greaterThan = [];
function insertNumbers(callback){
for (var i = 0; i<11; i++)
{
numbers.push(i)
}
callback(); // now execute the callback funtion
}
function takeNumbersGreaterThan(number){
for (var m = 0; m<numbers.length; m++)
{
if (numbers[m] > number)
{
greaterThan.push(numbers[m]);
}
}
console.log(greaterThan);
}
insertNumbers(function() { // here we send a functions as argument to insertNumbers which will execute when callback() is called
takeNumbersGreaterThan(5);
});
insertNumbers takes a argument called "callback". When insertNumbers is finished we simply run callback(). In the initial call to insertNumber we pass a function as argument which will be executed as soon as insertNumers finished (or callback() is called).
Code (for the most part) is executed sequentially. In the code you've provided, the computer runs though the code in the order you've provided it. First it creates a new array object and sets it to the numbers variable, then it creates a new array object and sets it to the greaterThan variable.
Then, it runs the insertNumbers function. Now what the computer does is jump to the code that you've defined in insertNumbers and executes all that code. Then, after it finishes with that, it'll return to executing the initial thread of code it was on which is back at line 4. So now it'll jump to the takeNumbersGreaterThan code. So functionally, you don't need any callbacks since your code doesn't do anything that takes an arbitrary amount of time.
That being explained, you see that takeNumbersGreaterThan doesn't get executed until after insertNumbers is executed.
The only time code isn't executed sequentially is when you start doing multi core/threaded code.
Callbacks are used when something takes an arbitrary amount of time like when you are reading data from a disk or are requesting data from the network.
Callbacks can exist, because functions defined in javascript (and many other langauges) exist as objects in the code. If you don't put the parentheses after a function name, you're actually referencing the function object just like any other variable. So you can pass that function object around in your code and to other bits of code. That is what is happening in this example.
setTimeout(myCallback, 5000)
function myCallback(){
console.log("5 seconds have passed");
}
So, as you can see, I can take my function myCallback and give it to another function, in this instance setTimeout, to use after the other function has completed a task.

Categories

Resources