How to execute Console.log and setTimeout sequentially in JavaScript - javascript

(function() {
console.log(1);
setTimeout(function(){console.log(2)}, 1000);
setTimeout(function(){console.log(3)}, 0);
console.log(4);
})();
Hello All,
When I run the above code, it produces the following output: 1,4,2,3
So, instead of producing 1,4,2,3 I want the output to be 1,2,3,4 but by using setTimeout() method only.
Can anyone please help me out on how to produce 1,2,3,4 by having setTimeout() method and making modifications to it.

To simplify things.. wrap the setTimeout with a Promise - that will give you the ability to also use async and await keywords and simplify your logic
(async function() {
function sleep(interval) {
return new Promise(resolve => {
setTimeout(resolve, interval)
})
}
console.log(1)
await sleep(1000)
console.log(2)
await sleep(1000)
console.log(3)
await sleep(1000)
console.log(4)
})();

Related

Understanding the order of async calls and setTimeouts

The code below contains a function (logger) that sets a timeout, then consoles an async function, then consoles an element ('c').
The output here is 'a', 'b', 'c'.
How is it that 'c' waits for the other two to return? The await call is inside a console.log, so I thought the 'c' console will go ahead and execute since await isn't at the beginning of the console call for 'b'.
In other words, I thought the output should be 'c','a','b'.
Any enlightenment here would be much appreciated!
async function apiCall() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('b');
}, 50);
});
}
async function logger() {
setTimeout(() => console.log('a'), 10);
console.log(await apiCall());
console.log('c');
}
logger();
The await inside the console.log() call represents a point at which the logger() function will return an intermediate promise. Note that the line of code is equivalent to
let p = await apiCall();
console.log(p);
The expression parameters in a function call are evaluated before the function is called. Thus, the whole function (logger()) has to wait for the promise to resolve before it can proceed to call console.log().

Why does this sequence of await function calls run in the wrong order?

I want to output some text after 2 seconds first, after output some "alert()" second and at the end output some "console.log" by using only async/await. Please help me how to write such a sequence?
Why the code below does not work
async function qaz()
{
let res1 = await setTimeout(function(){
console.log("show me first");
}, 2000);
let res2 = await alert('show me second');
let res3 = await console.log('show me at the end');
return [res1,res2,res3];
}
The setTimeout is part of the JavaScript asynchronous methods (methods that are starting to execute and their result will return sometime in the future to a component called the callback queue, later to be executed)
What you probably want to do is to wrap the setTimeout function within a Promise and await it and then execute the rest of the synchronous code.
const longTask = () => new Promise(resolve => {
setTimeout(function(){
console.log("show me first");
resolve();
}, 2000);
});
async function qaz()
{
await longTask();
alert('show me second');
console.log('show me at the end');
}
qaz();
I suggest to read more about the event loop model here
Neither the setTimeout, the alert, or the console.log return promises, and that's a problem because await only works with promises.
You can still use async/await, however. Create a delay function that returns a promise you can await for the first part, and then after that resolves do your alerts and your logging.
function delay(n) {
return new Promise(res => {
setTimeout(() => res(), n);
});
}
async function qaz() {
await delay(2000);
console.log('Show me first');
alert('Show me second');
console.log('Show me at the end');
}
qaz();

Best way to handle case where same code must run either immediately or after a promise resolved

Depending on a certain condition x, I need to perform a redirect either right now or after a promise asyncFunction resolved:
if (x) {
await asyncFunction();
redirectToA();
}
redirectToA();
That's quite ugly though. Is there a way to simplify this code so that redirectToA(); appears only once?
I think you could simply do this:
if (x) {
await asyncFunction();
}
redirectToA();
This is an example showing you that the redirectToA() will wait:
async function asyncFunction() {
return new Promise(resolve => {
setTimeout(() => {
resolve()
}, 3000)
})
}
function redirectToA() {
document.getElementById('status').innerText = "Redirected"
}
(async function() {
// your code is here
if (true) {
await asyncFunction()
}
redirectToA()
})()
<p id="status">
Running
</p>
It may not be an issue but I would be inclined to call redirectToA() at nextTick+ under both conditions.
await (x ? asyncFunction() : Promise.resolve());
redirectToA();
Thus, you are better guaranteed consistent redirect behaviour and may possibly benefit from less testing.

How to define a async-Function?

how can i define a function, that is called asynchronously?
async function getPosts() {
for (i = 0; i < 1000000000; i++){}
console.log("loop done.");
}
console.log("start");
getPosts();
console.log("end");
the result is:
start
loop done.
end
i was expecting:
start
end
loop done
i expect that, because the function "getPosts" is declared as "async".
so the we dont wait until the function is finished.
How do i have to adjust my code to get the expected result?
The async function could be the one calling another function that returns a Promise. Inside the Promise you could put a setTimeout instead of the for loop and finall make the call with asyncCall:
function getPosts() {
return new Promise(resolve => {
setTimeout(() => {
resolve('done.');
}, 2000);
});
}
async function asyncCall() {
var result = await getPosts();
console.log(result);
}
console.log("start");
asyncCall();
console.log("end");
The main reason why your code don't do the "async" thing, it's because of the way js threads works. A FOR loop will use the main thread to do the job soooo, the code will wait it finish de loop. The #shys answer works, but without the loop.
If you want a working async, take a look at the WebWorker api
To sum up what Mauricio Sipmann and shrys correctly told: An asynchronous function is a function which operates asynchronously via the event loop (see async function). In order to continue executing the calling context of your async function getPosts(), i. e. with console.log("end"), the event loop must be given a chance to pause the execution of getPosts(), e. g. with this variant of your function:
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)) }
async function getPosts() {
for (i = 0; i < 1000; i++) { await sleep(3) } // pause for 3 ms
console.log("loop done.");
}
console.log("start");
getPosts();
console.log("end");
But how is the fetch()-Method implemented?
fetch() likely contains such an await statement, so that the event loop can continue executing while fetch() is waiting for the HTTP response.

Why `async/await` doesn't work in my case?

I read about async/await, but I've a critical question.
At first I explain an old example to show base of my question and then I ask my exact question.
Everybody know it:
console.log('1');
console.log('2');
console.log('3'); // Ex: 123
It is simple but in below case:
console.log('1');
setTimeout(()=>{
console.log('2');
},0);
console.log('3'); // Ex: 132
It is simple too, setTimeout function is asynchronous and JavaScript jump from it and after resolve run its function, so we see 2 after 1 and 3.
But, now I read async/await and I wrote a function like this:
(async function test() {
console.log('1');
await setTimeout(()=>{
console.log('2');
},0);
console.log('3');
})(); // Ex: 132
The Export is 132 too, why? this is my question, why 3 run before 2? I expect because of async/await after 1 JavaScript wait for 2 and then wrote 3. why 132?
await only suspends when the value passed to it is a Promise. In your case, setTimeout returns a Number so await doesn't wait for it.
The correct code will be as follows:
async function test() {
console.log('1');
await new Promise((resolve, reject) => {
setTimeout(() => {
console.log('2');
resolve()
}, 0);
});
console.log('3');
}
Because setTimeout doesn't return a promise. await x only waits if x is a promise; if x isn't a promise, it's (effectively) wrapped in one as though you had await Promise.resolve(x). That means the code following it will run asynchronously but as soon as possible.*
If you want a promise version of setTimeout, see this question's answers. But even with that, your test function wouldn't use a callback, instead you'd just await the promise-enabled timeout:
function later(delay) {
return new Promise(function(resolve) {
setTimeout(resolve, delay);
});
}
async function test() {
console.log("1");
await later(10);
console.log("2");
console.log("3");
}
test().catch(e => console.error(e));
console.log("After the call (just to prove it does wait for the timeout after 1 and before 2");
* On browsers, that's guaranteed to be before a setTimeout(..., 0) scheduled during the same task, because promise callbacks scheduled during a task occur just after the end of that task, before the next task is picked up from the queue (even if the next task was scheduled before the promise callback). More on this ("macrotasks" and "microtasks") in this question's answers.
You can await to that functions that returns Promise. setTimeout does not returns Promise. So in this case await used before the setTimeout does not has a sense.
You can wrap your setTimeout into a Promise and call resolve at the setTimeout function.
(async function test() {
console.log('1');
await new Promise((resolve, reject) => {
setTimeout(() => {
console.log('2');
resolve(); // also can pass a parameter here to get it via await.
},0);
});
console.log('3');
})();

Categories

Resources