Why does this simple callback execute before the setTimeout? - javascript

This snippet logs 'output 2' ahead of 'output 1', which is cool due to the setTimeout.
const func1 = () => {
setTimeout(() => {
console.log('output 1');
}, 3000);
};
const func2 = () => {
console.log('output 2');
};
func1();
func2();
In this snippet, I used a callback, but it gave me the same result as the last snippet, why doesn't func1 execute before func2? How can I make func2 execute after func1?
const func1 = () => {
setTimeout(() => {
console.log('output 1');
}, 3000);
};
const func2 = () => {
console.log('output 2');
};
const main = (a, b) => {
a();
b();
};
main(func1, func2);

why doesn't func1 execute before func2
It does.
Func1 sets a timeout running
Func2 logs
3 seconds later the callback function you pass to setTimeout is called
If you want to make Func2 run after step 3, then you need to call it at the end of the callback you pass to setTimeout.

JavaScript does not wait for setTimeout to finish and then execute next functions.
whenvever javascript encounters a setTimeOut it store functions with provided timeout, in this case 3 seconds. after storing it in call stack it just starts to execute functions below it and since there is nothing in second function it get executed right away ( before 3 seconds obviously ). that's why you are seeing the log of second function before the log of first function.
To execute first function and then execute second function you can use promise chaining.
Example:
return new Promise(function(resolve, reject) {
setTimeout(() => {
console.log('output 1');
resolve();
}, 3000);
}).then(function(result) {
console.log('output 2');
});
Hope it will help. Feel free to correct if i am wrong.

Simple explanation -
Function 2 wouldn't wait for the completion of the timer started in function 1.
func1();
func2();
When you execute both functions, function 1 sets the timer and function 2 logs out.
Eventually, function 1 logs out after 3 seconds.
Your second snippet does pretty much the same.

Related

How to call the setTimeout? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I am being given the below mentioned code and asked to print the console after 3 seconds - B and C after A.
I tried
setTimeout(main(),3000);
But I get no output.
function sleep(){
}
function main(){
console.log('A');
// call after 3 sec
console.log('B');
// call after 3 sec
console.log('C');
}
}
setTimeout(main , 3000);
remove function call '( )'
How setTimeout works:
You specify the function (as a first argument) to be called after your timeout (second argument: 3000)
Generally you should pass the function by name to the setTimeout function without calling it.
setTimeout(main,3000);
setTimeout(main(), 3000) will execute main immediately because you put the () after it. Just use the name. setTimeout(main, 3000)
Also, you'll want to put your timeout on the two specific log statements you want to call later, not the whole function, or you could also log A outside of the main function and then call the main function after the timeout.
function main() {
console.log('A');
// call after 3 sec
setTimeout(() => {
console.log('B');
console.log('C');
}, 3000);
}
main();
try this
setTimeout(main,3000);
function main(a){
console.log('A');
setTimeout(function(){
console.log('B');
setTimeout(function(){
console.log('C');
}, 3000);
}, 3000);
}
You are calling the function in the first parameter of setTimeout. It is supposed to be a callback function(function definition). Just copy the code of the main function inside the setTimeout function and it will work.
The setTimeout Function is used usually with two parameters.
The callback function
Time in milliseconds
The callback function is called after a given time (second param).
This is how it is called:
const callbackFunction = () =>{
console.log("Inside callback");
}
setTimeout(callbackFunction, 2000);
OR simply
setTimeout(() =>{
console.log("Inside callback");
}, 2000);
Output (after 2 secs)
Inside callback
Above output could also be reproduced using async-await:
function sleep(time) {
return new Promise(resolve => {
setTimeout(() => {
resolve("");
}, time);
});
}
async function main() {
await sleep(0);
console.log('A');
// call after 3 sec
await sleep(3000);
console.log('B');
// call after 3 sec
await sleep(3000);
console.log('C');
}
main();

How to react on function that setting timeout

I have function:
function a(){ setTimeout(()=>{console.log('a')}, 0) }
This function send console.log on very end of callstack isn't it?
How can I write a function that runs after this console.log
the only way i found is send function on the of of callstack in the same way
a();
setTimeout(()=>{ console.log('after a'), 0 });
But it looks bad for me. I tried with promise, but i can react then on 'a' function not on console.log inside.
function 'a' is uneditable
you can use "callback" , a reference to another function to the a( ) function. Example:
function yourFunctionToBeRunnedAfter(){
..
..
}
function a(callback){
setTimeout(()=>{
console.log('a');
calback(); // ==> here is your function execution.
}, 0);
}
a(yourFunctionToBeRunnedAfter);
if you have parameters to pass to the callback() call, you can use apply() or call() or bind() or the spread operator (...) example:
function a(callback,...params){ // ... is the spread operator
setTimeout(()=>{
console.log('a');
callback([...params]); // ==> here is your function execution by spreading your params to the callback call.
}, 0);
}
a(yourFunctionToBeRunnedAfter, 1,2,3);
You need to use a promise. I'd recommend using async-await, but it really depends on your preference.
function a () {
return new Promise(resolve => {
setTimeout(() => {
console.log('a')
resolve()
}, 0)
})
}
a().then(() => console.log('after a'))
If you need to know when timeouts finish often, I'd recommend making a helper function:
const wait = (time) => new Promise(r => setTimeout(r, time))
Then you can use it like so:
(async () => {
console.log('Hello')
await wait(1000) // wait 1 second
console.log('Hello a second later')
})()

Why does my code print in this sequence? (Javascript promises)

I'm trying to understand promises/asynchronous programming, and I don't understand why this code prints "1 2 0" rather than "2 1 0". From the third block of code: shouldn't f1 fire only after f2 logs "2" to the console?
const f1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(console.log(1));
}, 1000)
})
const f2 = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve(console.log(2))
}, 1500)
})
f2.then(
f1.then(()=>{
setTimeout(()=>{
console.log(0);
}, 500)}
));
I'm trying to work on a program that needs several (like 6ish) asynchronous functions to fire in a very specific sequence, i.e. f2() must wait until f1() fully receives data from a request to execute, and I'm actually not sure how to do this...
You are running your f1 and f2 operations in parallel, starting them both one after the other. Both are started and then they are both in flight at the same time.
Then, you need to pass a function reference to .then() so it's a function that the promise infrastructure can call sometime in the future (when the host promise resolves). Instead, you are passing a promise to .then() which doesn't do anything useful.
If you change your code to this:
const f1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(console.log(1));
}, 1000)
})
const f2 = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve(console.log(2))
}, 1500)
})
f2.then(() => {
f1.then(()=> {
setTimeout(()=>{
console.log(0);
}, 500)}
});
});
Then, you will start both the f1 and f2 timers immediately. Then, only after both f2 and f1 finish will you start the third timer and you should get the output 1 2 0. 1 comes first because it's a shorter timer than 2 which are both running in a parallel. 0 comes last because it's timer isn't started until both 1 and 2 are done.
If you want to chain them to get 2 1 0, then you have to not start 2 and 1 at the same time. Make f1 and f2 into functions, not promises so you can sequence when they are called.
function delay(t) {
return new Promise(resolve => {
setTimeout(resolve, t);
});
}
function f1() {
return delay(1000).then(() => {
console.log(1);
})
}
function f2() {
return delay(1500).then(() => {
console.log(2);
})
}
function f3() {
return delay(1500).then(() => {
console.log(0);
})
}
// chain them together
f2().then(f1).then(f3).then(() => {
console.log("done");
});
This kind of .then() chaining basically says this:
Execute f2()
Register a .then() handler on the promise that .f2() returns so that when that promise resolves, it will then (and only then) call f1.
On the new promise that f2().then() returns, register a .then() handler on it so that when f1 is done, it will then call f3.
On the new promise that f2().then().then() returns, register a callback that will be called when f3 is done.

JS: Create function that returns function that, when invoked waits for the specified amount of time before executing

My objective is to:
Write a function delay that accepts two arguments, a callback and the wait time in milliseconds. Delay should return a function that, when invoked waits for the specified amount of time before executing. HINT - research setTimeout();
I tried the code below:
const delay = (inputFunc, waitTime, ...args) => {
return function () {
return setTimeout(inputFunc(), waitTime, ...args)
}
}
// UNCOMMENT THE CODE BELOW TO TEST DELAY
let count = 0;
const delayedFunc = delay(() => count++, 1000);
delayedFunc();
console.log(count); // should print '0'
setTimeout(() => console.log(count), 1000); // should print '1' after 1 second
I get the error:
TypeError [ERR_INVALID_CALLBACK]: Callback must be a function at setTimeout (timers.js:390:11)
What am I doing wrong? What should the answer be?
setTimeout(inputFunc(), waitTime, ...args)
This means "immediately call inputFunc(), then pass its result in as the first parameter to setTimeout (along with waitTime and args)". Instead you want:
setTimeout(inputFunc, waitTime, ...args)
Another option, particularly if you need to do extra things when the timeout goes off, is to create an additional function, and that function will call inputFunc. For example:
setTimeout(() => {
// do some cleanup stuff related to delay
inputFunc();
}, waitTime, ...args);
function delay(callback, waitTime, ...args) {
return function () {
return setTimeout(callback, waitTime, ...args)
}
}
Basically had it just don't need those () on the callback

How to use call back to make a function execute after another in setTimeout condition

I have some code which can be mimicked by this situation
function abc(def){
setTimeout(1500,function(){
console.log('1');
}
def();
}
function def(){
console.log('2'}
}
I want 2 to be printed after 1 - how do I do that?
If you want a function to also be called after a delay... just put it inside the delay. I've added some extra console logs and fixed some of your code. Run the below example to see how it works.
function def() {
console.log('2 - def()');
}
function abc() {
console.log('before');
setTimeout(function() {
console.log('1');
def();
}, 1500);
console.log('after');
}
abc();
function abc(def){
setTimeout(1500,function(){
console.log('1');
def();
}
}
You can use async and await. Wrap the setTimeout(...) in a Promise and resolve Promise inside the callback passed to setTimeout.
async function abc(def){
await new Promise(res => {
setTimeout(function(){
console.log('1');
res();
},1500)
})
def();
}
function def(){
console.log('2')
}
abc(def)
setTimeout(function, milliseconds) takes a function has the first parameter and delay value (time in milliseconds) as the second parameter. You were passing them in the wrong order.
Also in your example def() was printing 2 and it was outside the setTimeout function, so it could not have possibly printed 2 after 1 (as 1 was being logged inside the setTimeout, which means it would be executed after the delay of 1.5 seconds).
The solution provided by Chris above is correct and would do what you wanted (print 2 and then 1)

Categories