如何在javascript中同步使用setTimeout?
How to use setTimeout synchronously in javascript?
是否可以使用 setTimout
得到下面提到的输出。如果是,请分享您的想法:-
console.log("1st");
setTimeout(()=>{
console.log("2nd");
},0);
console.log("3rd");
**输出应该是**
1st
2nd
3rd
使用async/await:
const foo = () => new Promise(resolve => {
setTimeout(() => {
console.log("2nd");
resolve();
}, 0);
});
(async () => {
console.log("1st");
await foo();
console.log("3rd");
})();
Majed Badawi 的回答展示了一种实现您想要的东西的方法,但它只是一个类似于简单地将您的第 3 个日志放在第 2 个之后的 setTimeout 回调中的结构。
这有重要的概念原因。
JavaScript 是一种事件驱动语言,其中有一种叫做事件循环的东西,它正在检查新事件并不停地处理它们。
您在这里寻找的是一种使用 setTimeout
的方法,就像您在 PHP、C 或其他语言中使用 sleep
一样。它根本不存在。
sleep
是阻塞指令:程序在继续之前等待 X 秒。如果您在 JavaScript 中执行此操作,您将阻止事件循环进入 运行ning 并且您甚至不想尝试执行此操作。如果你真的坚持,你可以在 while
语句中检查是否已经过足够的时间,这将在前端环境中冻结你的浏览器或阻止在后端环境中处理新请求。
这里有更多内容https://cloudoki.com/js-dont-block-the-event-loop/
相比之下,setTimeout
会在一段时间后向提供的侦听器触发事件,程序的其余部分(和事件循环)将继续 运行。
sleep
不存在,但你可以自己制作
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)
觉得async..await
太神奇了?让我们试试发电机 -
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)
发电机太复杂?让我们尝试一个 low-level 抽象 -
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)
是否可以使用 setTimout
得到下面提到的输出。如果是,请分享您的想法:-
console.log("1st");
setTimeout(()=>{
console.log("2nd");
},0);
console.log("3rd");
**输出应该是**
1st
2nd
3rd
使用async/await:
const foo = () => new Promise(resolve => {
setTimeout(() => {
console.log("2nd");
resolve();
}, 0);
});
(async () => {
console.log("1st");
await foo();
console.log("3rd");
})();
Majed Badawi 的回答展示了一种实现您想要的东西的方法,但它只是一个类似于简单地将您的第 3 个日志放在第 2 个之后的 setTimeout 回调中的结构。
这有重要的概念原因。
JavaScript 是一种事件驱动语言,其中有一种叫做事件循环的东西,它正在检查新事件并不停地处理它们。
您在这里寻找的是一种使用 setTimeout
的方法,就像您在 PHP、C 或其他语言中使用 sleep
一样。它根本不存在。
sleep
是阻塞指令:程序在继续之前等待 X 秒。如果您在 JavaScript 中执行此操作,您将阻止事件循环进入 运行ning 并且您甚至不想尝试执行此操作。如果你真的坚持,你可以在 while
语句中检查是否已经过足够的时间,这将在前端环境中冻结你的浏览器或阻止在后端环境中处理新请求。
这里有更多内容https://cloudoki.com/js-dont-block-the-event-loop/
相比之下,setTimeout
会在一段时间后向提供的侦听器触发事件,程序的其余部分(和事件循环)将继续 运行。
sleep
不存在,但你可以自己制作
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)
觉得async..await
太神奇了?让我们试试发电机 -
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)
发电机太复杂?让我们尝试一个 low-level 抽象 -
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)