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