I have a super simple question. I have an onclick function that takes a good 10 seconds to complete. Therefore I want to add a 'Loading, please wait' text while the function completes.
If I do this:
javascript:
function onclickFunction(){
addPleaseWait();
runSlowFunction();
addFinishedText();
}
Then of course the end result is that the slow function runs first, then addPleaseWait and FinishedText run 2nd and 3rd. What is the proper way to do this?
If you are allowed to use ES6 function, I would suggest you use promise to run your function.
function onclickFunction() {
startLoader();
longFunction().then(function(data) => {
// long function is done, remove loader
return removeLoader();
})
}
function longFunction() {
return new Promise(function(resolve, reject) {
/*
* the parameter resolve tell when to finish. If you pass a function, it will finish once all the instruction of the function is done.
* the parameter reject is used to manage error.
*/
resolve(function() {
// Do you long function stuff
})
})
}
This method could seams a little bit complicated for what you are trying to achieve, but I think it is a great way to handle slow function. To make sure everythings comes in the right order.
If you wish to learn more about promise, look at this Mozilla docs link
function call() {
//your function here for example :
$("#yourFunction").html("yourFunction is executing....");
$("#test").html("Please Wait....."); // during your function
setTimeout(function() {
$("#yourFunction").html("yourFunction is completed....");
$("#test").html("done!!!!"); // after your function completed
}, 1000); // if you need more or less time change here
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<button onclick=call()>Click</button>
<div id="yourFunction"></div>
<div id="test"></div>
You need a callback in your slow function, for example
runSlowFunction(callback) {
// ... do all slow things, and in the end, call your function
callback();
}
& then, your onclick function changes to
function onclickFunction(){
addPleaseWait();
runSlowFunction(addFinishedText);
// pass addFinishedText as the callback,
// which gets called after the slow function is done
}
Related
I just realized that I do not understand javascript enough, despite the fact that I have been coding it for some time.
What I am not comfortable is Javascript Async.
until now I have been using callback and promise, because documentations and tutorials did it so as below.
$.get("some/url", function() {
// callback body
})
axios.get('some/url').then(res => {
console.log(res.data);
});
arr.map(element => console.log(element))
I know callback is used to my our code asynchronous
function doSomething(cb) {
console.log("this function receives callback function");
cb();
}
but what if we just call the function inside the function manually
function func1() {
// function body
}
function doSomething() {
console.log("this function receives callback function");
func1();
}
What I thought is as long as function is called at the right time, we do not have to use callback.
or is it because callback does its work while some other operations are going on?
If so, doesnt it break the principle of javascript as single threaded?
because its doing two things at the same time.
besides, do people use promise over callback function because of its readability and you could use Promise.all() ?
I feel like I am missing a core advantage of using promise.
Kindly please help me understand better.
If you don't use a callback, then you can only call func1(). The original doSomething() is more general, since you can call different functions depending on what the caller needs.
function func1() {
// function body
}
function func2() {
// function body
}
doSomething(func1);
doSomething(func2);
Is exactly the difference between hard coding data in your code or getting it dynamically.
In backend for example you make the code so it can serve different users different needs... at the same time, the same code...
So in this example:
function doSomething(cb) {
console.log("this function receives callback function");
cb();
}
you can build a functions that serve different users different information depending on the cb it receives...
in this example:
function func1() {
// function body
}
function doSomething() {
console.log("this function receives callback function");
func1();
}
it just runs a specific function func1 and that's it
It is all about reusability. If you call pass your callback into the utility function, in your example it is doSomething, you will not be able to reuse doSomething function in other parts of your program. You have just created a tight coupling between two functions.
If you program to the interface, and define which kind of callback you are expecting in your doSomething function, you will be able to use this doSomething function anywhere. It will not have to know which exact function to call, it will just concern about having a callback which expects n parameters in some order which.
In this article which I was referred to the following statement is made:
Callbacks are a way to make sure certain code doesn’t execute until other code has already finished execution.
The article then goes on to illustrate this with an example:
function doHomework(subject, callback) {
alert(`Starting my ${subject} homework.`);
callback();
}
doHomework('math', function() {
alert('Finished my homework');
After this the articles states:
As you’ll see, if you type the above code into your console you will get two alerts back to back: Your ‘starting homework’ alert, followed by your ‘finished homework’ alert.
The implication seems to be that by using a callback the desired order of code execution has been ensured. That is you start your homework before you finish it. However, I feel I may have misunderstood the whole point of the article and therefore still do not understand callbacks and asynchronous code because when I slow down the first part of the doHomework function using setTimeout() the code executes (or at least returns) in the opposite order:
function doHomework(subject, callback) {
setTimeout(function(){
console.log(`Starting my ${subject} homework.`);
}, 500);
callback();
}
doHomework('math', function() {
console.log('Finished my homework');
});
The result I get from that is:
steve#Dell ~/my-app $ node app.js
Finished my homework
Starting my math homework.
});
I am using node here (hence console.log() replaces alert()) but I do not think that is relevant.
It seems to me I have missed something quite fundamental and need to try and access what it is that I am trying to understand before I then try and understand it.
Any assistance on this journey would be greatly appreciated.
After getting great feedback I think the homework analogy was not helpful so I am now using the first code example in the article I referenced. The article gives this code:
function first(){
// Simulate a code delay
setTimeout( function(){
console.log(1);
}, 500 );
}
function second(){
console.log(2);
}
first();
second();
The above returns 2 then 1 in the console.
I tried (without success) to reverse the return order to 1 then 2 with this:
function first(callback){
setTimeout(function(){
console.log(1);
}, 500);
callback();
}
function second(){
console.log(2);
}
first(second);
The answer I got from Cleared (before it was edited) was to put the callback() inside the setTimeout() function. He used the homework example but here it is with this example:
function first(callback){
setTimeout(function(){
console.log(1);
callback();
}, 500);
}
function second(){
console.log(2);
}
first(second);
I think that is closer to what I am imagining the article was getting at. It seems to make sense although I guess the precise context of what you are doing and what you want to happen determine what is right or wrong.
In general, the call to the callback is not at the end of the function, but rather after you have done the important things.
So if I understand your question, the doHomework-function should start doing homework (which takes time, in this case 500ms), and then the homework is finished. So the important things in your case is the console.log('Starting my ${subject} homework.'); which "takes 500ms" (since this is the time you need to do the homework).
Therefore, you should put the call to the callback right after console.log('Starting my ${subject} homework.');, i.e.
function doHomework(subject, callback) {
setTimeout(function(){
console.log(`Starting my ${subject} homework.`);
callback();
}, 500);
}
doHomework('math', function() {
console.log('Finished my homework');
});
Generally, you would call the callback function when you are finished doing whatever it is you are doing.
So you have the code inside and outside your setTimeout function backwards.
function doHomework(subject, callback) {
console.log(`Starting my ${subject} homework.`);
setTimeout(function(){
console.log(`Finished my ${subject} homework.`);
callback();
}, 500);
}
What exactly is callback?
Callback meaning function-in-function like recursive.
Let me give you an example:
Every day we eating then sleeping. But in JS code, JS is an impatient language unlike PHP. This is the example code:
// Consuming 3s to eating(just an example, not really 3s)
function eating() {
setTimeout(function() {
console.log('Eating...');
}, 3000);
}
// Then go to sleep
function sleep() {
console.log('Z..Z..Z');
}
eating();
sleep();
But you sleep immediately after...(When we run the code it runs the sleep first then eating())
To assure that everything works in order, meaning you only go to bed when done eating. So we need the eating() to tell when it's done to start the sleep():
// Consuming 3s to eating(just an example, not really 3s)
function eating(callback) {
setTimeout(function() {
console.log('Eating...');
callback() // the function which will be proceeded after "Eating..."
}, 3000);
}
// Then go to sleep
function sleep() {
console.log('Z..Z..Z');
}
// call the function
eating(function() {
sleep();
});
Yeah! Right now I think you can use callback in your code!
Where you can see callback?
You can see it in every JQuery code:
$("#hide").click(function(){ //the click() function call the function inside it which is callback
$("p").hide();
});
$("#show").click(function(){
$("p").show();
});
Callbacks in Javascript are used in asynchronous programming, where you can't ensure that the code above is running before the code below, like loading files from a server asyncronous.
The problem is, that with normal sequential programming, you can not ensure, that the data you fetch is fully loaded when the programm is running (i.e. if you run the script, one time the variable could be setted, another time it could be undefined, cause async task is still running), so you set a callback function, which gets connected to different states, ie. success or error on ajax call. The difference to normal programming flow is, your programm does not stop till it has loaded the data (or in your case, the timeout doesnt pause your program, the code afterwards is computed and the timeout can run of anytime, if you dont use a fix value).
So, to ensure that your code will run when the needed logic finishes, you have to pass a callback function, which is executed when the needed state is fulfilled (i.e. success/error on loading tasks, or a timeout is "finished".
The homework example IMO isnt the best sample, cause it doesnt touch the real use cases, as it always "waits" 500ms.
In your example the problem is, your "callback" is out of the "asyncronous" part of code, so its executed directly after starting the timeout, even if the timeout still is "running". Maybe your thinking of SetTimeout is the problem, in my javascript beginnings I thought its more like "pause for 500ms", but its "execute the scoped code after waiting for 500ms out of the normal code flow"
Here are some more informations, I can recommend the whole page, even if your not javascript noob ;)
https://javascript.info/callbacks
What is the best way to wait for a function to complete before the next function is called?
I have a scenario where two functions are called consecutively, one after the other. I need the first one to complete before the second one is called.
Function1();
Function2();
How do I tell the code to wait for Function1 to complete before attempting Function2?
WebDevelopment: solution can be javascript or jQuery, or Ajax based.
Thanks...
You can do many ways but a very simple Example
function first(){
// define every thing here and then at the end call your second function
function2();
}
Checkout more possibilities here
You could either use Promise or callback to solve this problem, with Promises being the more modern and cleaner way of doing things:
Promise:
function foo() {
return new Promise(function(resolve, reject) {
// do some work
resolve(optionalParam);
// something caused an error whoops
reject(optionalParam);
})
}
function bar() {
// do something
};
// Call bar only once foo finishes
foo().then(function() {
bar();
}, function() {
// this is the reject case an error here
});
Promises are able to be chained, meaning that if bar was a Promise we could chain another then event to that.
You could also use callbacks to solve your problem
function foo(cb) {
var data = 'alex';
cb(data);
}
function bar(name) {
// some processing
console.log(name);
}
// Call foo, then execute bar when foo finishes
foo(function(data) {
bar(data); // alex would be logged once the callback fires
});
In the callback example here, we pass a function as a parameter, once the running function block encounters your invocation of the cb parameter, it will invoke the function which emulates the asynchronousy. Just remember though that it does not stop the execution context on that function. If we had code like:
function foo(cb) {
var data = 'alex';
cb(data);
console.log('this is after so don't print it'); <-- still prints
};
The final console.log will print when the callback finishes its time on the event queue (unless of course you fire an even in CB like a http request, in which the log will fire and then the http request would finish after).
To stop the last console log you would need to explicitly tell javascript to return when cb is called to prevent further execution in that method, and personally this is where I favour Promises, once you resolve or reject the promise the execution context within that function scope is stopped.
if your in the browser, just use callback it's the easiest and cross-browser way to do it.
Exemple:
function sayBill() {
console.log('bill');
}
function sayHiAfterTwoSeconds(callback) {
setTimeout(function() {
console.log('hi');
// call the function you passed in parameter
if (typeof callback === 'function') {
callback();
}
});
}
sayHiAfterTwoSeconds(sayBill);
// will output 'bill hi'
https://jsfiddle.net/80bbbjco/
If you want better way to do it, but not cross browser there is promise : https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Promise
Or even more modern but not supported ATM async await: https://jakearchibald.com/2014/es7-async-functions/
I dont know why my code dont work. Please help!
$('nav').mouseout(setTimeout(function() {
$(this).removeClass('subm')
}, 1000));
Without setTimeout is work normaly.
setTimeout(...) is being called immediately. It returns the id number of the newly pending timeout. The timeout is only registered and called once here. The execution of your code is happening like this:
setTimeout(function() {
$(this).removeClass('subm')
}, 1000);
// = 2
$('nav').mouseout(2);
You need to pass .mouseout() a function that calls setTimeout each time. You also need to fix the this reference, which is different inside the setTimeout callback. This should fix both issues:
$('nav').mouseout(function() {
var self = this;
setTimeout(function() {
$(self).removeClass('subm')
}, 1000);
});
In javascript, like in most other languages, when you do this:
variable = some_function();
you're passing the return value of a function to a variable. Similarly when you do this:
a_function(another_function());
you're passing the return value of another function as an argument to a function.
This works the same in javascript, C, PHP, Ruby and even Fortran.
So, when you do this:
$('nav').mouseout(setTimeout(..));
You're passing the return value of setTimeout as an argument to mouseout. And setTimeout returns a number which can be used in clearTimeout. So you're basically doing this:
$('nav').mouseout(a_number);
What you want instead is to pass a function:
$('nav').mouseout(function(){setTimeout(..)});
Or if you find that hard to read then do this:
function handleMouseOut () {
setTimeout(...);
}
$('nav').mouseout(handleMouseOut); // note we're passing a function here
// not calling it
I am not very familiar with callback() functions. I am looking for an explanation and an example of what a proper use case might be. In my example below, how can I utilize a callback and also, should I?
Here I have two functions:
addShape = function () {
ExampleService.createShape(function () { //ajax
shapeMade = true;
//anything else etc.......
});
}
deleteShape = function () {
ExampleService.removeShape(function () { //ajax
shapeMade = false;
//anything else etc.......
});
}
The third function (focus of my question)
resetShape = function () {
deleteShape();
addShape();
console.log('example');
}
When I call the resetShape() function, the example gets logged to the console before both deleteShape() and addShape() have finished.
Would this be a situation to use a callback()? If so, how? If not, why?
Callbacks are used for asynchronous functions. In this case, since you have multiple async function to wait for, you probably want to use a Promise, and Promise.all to execute the callback when all async operations are complete:
resetShape = function () {
Promise.all([ deleteShape(), addShape() ]).then( function() {
console.log('example');
});
}
Note that, for this to work, your functions "deleteShape" and "addShape" have to return the promise object:
addShape = function () {
return new Promise(function(resolve, reject) {
ExampleService.createShape(function () {
shapeMade = true;
resolve();
});
});
A callback is used mainly for two reasons, to give another object or function a way to tell us something we were waiting for has completed (or changed) or a way to get something from us when they require it.
First case: imagine a function that makes an asynchronous request to
a server. We don't know how much time it'll take to complete, so we
give the requester a way to tell us it's done:
getDataFromServer('foo.php', callback); //callback will be called when the request
//is done. We can do something else meanwhile.
Second case. I could create and object that, when needed, will ask
for more data (ie, getting more rows to append to a table when we
scroll down)
var tableBuilder = new TableBuilder(container, dataGetterCallback);
dataGetterCallback will be called whenever TableBuilder needs more rows. It'll have the logic to give it to them (maybe by receiving a parameter that tells it in which index to start).
Hope this gives you an idea.