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')
})()
Related
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.
I'm still trying to figure out how the async/await works.
function func1() {
console.log('a');
func2();
console.log('b');
}
async function func2() {
console.log('1');
let value = await new Promise(resolve => setTimeout(function() { resolve('async') } , 2000));
console.log(value)
console.log('2');
}
func1();
How can I achieve output as below?
a
1
async
2
b
I try to make func2 as async and await the setTimeout, but then they whole func2 become async function. So it will print out this instead:
a
1
b
async
2
You can't make async into sync
But you can get the output you need
make func1 async and use await
async function func1() {
console.log('a');
await func2();
console.log('b');
}
async function func2() {
console.log('1');
let value = await new Promise(resolve => setTimeout(function() { resolve('async') } , 2000));
console.log(value)
console.log('2');
}
func1();
Synchronous means things are happening chronologically one after the other.
Asynchronous means things are happening chronologically independent of one another.
When you execute a task synchronously, you wait for it to finish before moving on to another task(one after the other).
When you execute a task asynchronously, you can move on to another task before the prior task finishes. But it can't be exactly guranteed.
So, in your code you've call an async function inside a sync funcion. So, accoding to above explanation, you can not gurantee that after calling async function func2() rest of the func1() will execute. Because func2() is an async funcation which you can't say how much time will it take l to end up its execution process. So, You can't make async become sync.
function func1() {
console.log('a');
func2(); // call a asyncronized method inside a syncronized method
console.log('b');
}
async function func2() {
console.log('1');
let value = await new Promise(resolve => setTimeout(function() { resolve('async') } , 2000));
console.log(value)
console.log('2');
}
func1();
But you can call that async function func2() inside func1() using await keyword so at the same time func1() will need to convert into an async function in order to use await keyword. So, in this way your desired output can be generated.
// change func1() as async method
async function func1() {
console.log('a');
await func2(); // use await keyword
console.log('b');
}
async function func2() {
console.log('1');
let value = await new Promise(resolve => setTimeout(function() {resolve('async') } , 2000));
console.log(value)
console.log('2');
}
func1();
I hope that this will help you to understand the problem.
I am trying to understand the difference between the 3 options:
.then(myCallback)
.then(myCallback())
.then(() => { myCallback() })
The myCallback function returns nothing and is used only for its side effects, so I don't need it to pass anything back to the promise chain. What I don't understand is why in my code only the second option triggers the function, when it seems like all the 3 should.
UPDATE: Here is the code with the bare essentials
serverCall(url, data) // fetch function
.then((response) => response.json())
.then(myCallback) // not running, only when () added
.catch((error) => { console.log(error) })
const myCallback = () => {
anotherServerCall(...).then(...)
}
UPDATE 2
After some digging I see that having .then((response) => response.json()) as the first then response is what is preventing .then(myCallback) to execute. Still no idea why...
All three should trigger the function, but the order differs between the approaches. If you're sometimes seeing evidence that the serverCall or myCallback aren't being invoked, then that has something to do with the particulars of those functions, not the ways you are calling them.
To demonstrate, consider two proxies for serverCall and myCallback that we know will always work. Let's apply each idea in your question to those:
This is the "normal" way to use then. Pass it a function that is invoked after the promise to which it is attached...
function serverCall() {
console.log('began server call');
return new Promise(function(resolve) {
setTimeout(() => {
console.log('completed server call');
resolve();
}, 2);
});
}
function myCallback() {
console.log('callback called');
}
serverCall().then(myCallback).then(() => console.log('done'));
// produces:
// began server call
// completed server call
// callback called
// done
Your first and third ideas are almost the same. Pass then a function which is invoked after the promise. In your third idea, the function isn't the callback, it's a function that calls the callback. One more stack frame, but the exact same effect...
function serverCall() {
console.log('began server call');
return new Promise(function(resolve) {
setTimeout(() => {
console.log('completed server call');
resolve();
}, 2);
});
}
function myCallback() {
console.log('callback called');
}
serverCall().then(() => { myCallback() }).then(() => console.log('done'))
// produces:
// began server call
// completed server call
// callback called
// done
Your second idea, as a commenter points out, invokes the function and passes it's result to then. The chaining of the then runs synchronously after starting the promise, so the results appear reordered: myCallback runs before the promise completes...
function serverCall() {
console.log('began server call');
return new Promise(function(resolve) {
setTimeout(() => {
console.log('completed server call');
resolve();
}, 2);
});
}
function myCallback() {
console.log('callback called');
}
serverCall().then(myCallback()).then(() => console.log('done'))
// produces:
// began server call
// callback called <------ CHANGED!!!
// completed server call
// done
The only way I've found to duplicate your problem is if the callback returns a function. Options 1 and 3 don't do anything because the returned function isn't being called. Option 2 is called and is successful.
function fetch() {
return new Promise((resolve, reject) => {
resolve();
});
}
function myCallBack() {
return function () {
console.log('Success');
};
}
fetch().then(myCallBack); // nothing
fetch().then(myCallBack()); // Success
fetch().then(() => myCallBack()); // nothing
Your use cases are different because
The first one then call, you are passing a callback to be invoked when then it’s executed, passing a naming function will appear in the stack trace if some error occurred
The second one, execute the callback passed before being passed to the then function and the result of that execution callback will be passing to the then function, so imagine this.
function myCallback(){
return function theRealCallbackPassed(thenResponse){
// do something with then response
}
}
The last one, will define an anonymous arrow function , so what is the diff between
then( () => {} )
And
then( function(){} )
The different is that using arrow function () => {} you have a short syntax and you are binded the function contexto to the current context where the arrow function it’s declared.
While the function() {} syntax is not shorter and it is not auto bindable.
Hope it can help you.
I have two functions and I need a forced delay between those two consecutive function calls. That is to say,
a // call func a
delay(100) // delay for 100 ms
b // call func b
Is there anyway to do so?
Edit: tried
a();
console.log("a");
setTimeout(b(), 1000);
console.log("b");
With new ES6, you can even make it more cleaner and look like sequential,
function delay(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
})
}
async function doItHere() {
console.log('a', Date.now());
await delay(5000);
console.log('b', Date.now())
}
doItHere();
All you need to do is to make use of setTimeout function to call b after calling a
a() // call func a
setTimeout(b, 100) // delay for 100 ms
if you need to keep b function bound to the current scope, use:
setTimeout(() => b(), 100) // () => {} functions are always bound to the current scope
Try this:
a() // First call function a
Then call function b in setTimeout function.
es5:
setTimeout(function() {b()},100);
es6:
setTimeout(()=> {b()},100);
I tried to simplify my code, in essence I have this:
function thirdPartyAPIMethod() { // Dummy method returning promise
return Promise.resolve();
}
function func1() {
console.log("func1 start");
return thirdPartyAPIMethod().then(() => {
console.log("func1 end");
// ...
resolve();
});
}
function func2() {
console.log("func2 start");
// ...
console.log("func2 end");
}
func1().then(func2());
I want to run func1 and when it completes then run func2. So I was expecting the output would be this:
func1 start
func1 end
func2 start
func2 end
But instead it prints this:
func1 start
func2 start
func2 end
func1 end
Can someone help me to do this?
Modify your func1 to invoke resolve after thirdPartyAPIMethod's promise has been resolved
function thirdPartyAPIMethod() //dummy method returning promise
{
return Promise.resolve();
}
function func1() {
return new Promise((resolve, reject) => {
console.log("func1 start");
thirdPartyAPIMethod().then( () => {
console.log("func1 end");
resolve(); //invoke resolve here so that func1() is chained with func2
});
});
}
function func2() {
console.log("func2 start");
console.log("func2 end");
}
func1().then( () => func2()); // then has function callback handler instead of return value of func2
In the call to then of the first promise, you're not passing a reference to func2, but calling it:
func1().then(func2()).catch(...);
Change it to:
func1().then(func2).catch(...);
If you want to pass parameters:
func1().then(() => func2(...)).catch(...);
Or, using the pre-ES6 syntax:
funct1().then(function() { return func2(...); }).catch(...);
Besides, when you define the promise you're not calling resolve and reject, so theoretically (except if you haven't posted all your code) that promise never completes:
function func1(...) {
return new Promise((resolve, reject) => {
console.log("func1 start");
thirdPartyAPIMethod().then({
console.log("func1 end");
resolve(''); // resolve the promise with whichever value you want
})
});
}
func1(...).then(func2(...)).catch(...);
in above code func2() is executing before passing as input.
Correct way would be
func1(...).then(func2).catch(...);
P.s the following code is equivalent to what you want to achieve.
thirdPartyAPIMethod().then(func2).catch(...)