JavaScript: How does a callback function work? - javascript

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.

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.

making a JavaScript function with callback

Write a function after that takes the number of times the callback needs to be called before being executed as the first parameter and the callback as the second parameter.
This sounds a bit like a homework assignment, so I'm hesitant to help you with your homework by answering the question for you ;)
Instead ... the basic idea is that you need to write a function with two arguments:
function (numberOfTimesToCall, callbackFunctionToCall) { //..
Inside you'll call the callback argument, using:
callbackFunctionToCall();
You'll want to do that a certain number of times, and in Javascript we typically use a for loop to do something a certain number of times.
For instance, to doSomething() five times, you could write:
for(var i = 0; i < 5; i++) {
doSomething();
}

How to properly use JavaScript callback without jquery

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.

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.

How to save value from a function inside socket.on to a global variable?

This is probably very simple, but I am fairly new to programming in Javascript and using Socket IO.
When I want to give a global variable a value from inside a function the process is fairly simple:
var j;
function a(){
j=2;
}
a();
//j is now 2
My issue now is, I have a method called socket.on, which has a function inside it, like this:
var j;
socket.on('news', function (p) {
j=p;
//in here, j is equal to p
});
//in here, j is NOT p, it is undefined.
Now, in this case I want my global variable j to have the value of p, but when I print j outside of the function, it is undefined. I assume this is because I need something like a(); outside the function like in the first example.
How can I do this in this case?
Thank you so much.
The second parameter of socket.on is a so called callback function, a very common pattern in javascript. In your example you are listening to the 'new' event. When this event occurs, the callback is fired with the argument p. Of course this argument is only available inside the callback function itself.
To be clear: You do not call the function in the second example directly. It is called once the 'news' event occurs.
The callback pattern is very handy, because it allows you to write non blocking code. While you are waiting for the 'news' event to occur, any code after your socket.on call is being executed normally. This is the reason why you cannot access p outside the callback: You don't know at what point in time the callback will be called.
I suppose you read a little more about Javascript's event loop or functions and their scope.

Categories

Resources