'How to use setTimeout synchronously in javascript?
Is it possible to get mentioned below output using setTimout. If yes, then please share your thought:-
console.log("1st");
setTimeout(()=>{
console.log("2nd");
},0);
console.log("3rd");
**Output should be **
1st
2nd
3rd
Solution 1:[1]
Majed Badawi's answer shows a way to kind of achieve what you want, but it is just a construct that would be similar to simply put your 3rd log inside the setTimeout callback after the 2nd.
There are important conceptual reasons for this.
JavaScript is an event driven language, where you have something called an event loop that is checking for new events and process them non stop.
What you are looking for here, is a way to use setTimeout as you would you would use sleep in PHP, C or others. It simply doesn't exist.
sleep is a blocking instruction: the program waits for X seconds before proceeding. If you do this in JavaScript, you will prevent the event loop from running and you don't want to even try to do this. If you really insist, you can check if enough time has elapsed in a while statement, this will freeze your browser in a front end environment or prevent the handling of new requests in a back end environment.
More on this here https://cloudoki.com/js-dont-block-the-event-loop/
In contrast, setTimeout will fire an event to the provided listener after some time, the rest of the program (and the event loop) will continue to run.
Solution 2:[2]
Using async/await:
const foo = () => new Promise(resolve => {
setTimeout(() => {
console.log("2nd");
resolve();
}, 0);
});
(async () => {
console.log("1st");
await foo();
console.log("3rd");
})();
Solution 3:[3]
sleep doesn't exist but you can just make it on your own ?
function sleep(ms) {
return new Promise(r => setTimeout(r, ms))
}
async function main() {
console.log(1)
await sleep(1000)
console.log(2)
await sleep(1000)
console.log(3)
await sleep(1000)
return "done"
}
main().then(console.log, console.error)
Thinking async..await are too magical? Let's try a generator -
function sleep(ms) {
return Task(k => setTimeout(k, ms))
}
function* main() {
console.log(1)
yield sleep(1000)
console.log(2)
yield sleep(1000)
console.log(3)
yield sleep(1000)
return Task(k => k("done"))
}
function Task(runTask) {
return {
runTask,
bind: f => Task(k => runTask(x => f(x).runTask(k)))
}
}
function coroutine(f) {
function then(v) {
let {done, value} = f.next(v)
return done ? value : value.bind(then)
}
return then()
}
coroutine(main()).runTask(console.log)
Generators too sophisticated? Let's try a low-level abstraction -
function sleep(ms, then) {
setTimeout(then, ms)
}
function main(then) {
console.log(1)
sleep(1000, _ => {
console.log(2)
sleep(1000, _ => {
console.log(3)
sleep(1000, _ => {
then("done")
})
})
})
}
main(console.log)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | AsTeR |
| Solution 2 | Majed Badawi |
| Solution 3 |
