如何在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)