为什么我的同步代码是异步执行的?

Why is my synchronous code executing asynchronously?

我正在尝试 运行 一些同步函数,它应该等待一定时间然后 return 控制。但出于某种原因,它一直异步执行,或者至少看起来是这样。

这是代码:

function pause(ms) {
  var dt = new Date();
  while (new Date() - dt <= ms) {
    /* Do nothing */
  }
}

console.log("start calculation..");
pause(3000);
console.log("calculation finished!");

这会立即在控制台中显示以下内容:

start calculation..
calculation finished!

完全没有延迟,好像暂停函数是异步执行的

我试过3种不同版本的暂停功能,都没什么区别。

你可以在sandbox我放代码的地方看到这个
(您必须转到首选项 - sandbox.config.json 并打开“无限循环保护”才能工作)

  1. 为什么代码 运行 不同步,首先显示“开始计算...”消息,然后在延迟 3 秒后显示第二条消息?
  2. 是否有更好的方法来模拟 运行 耗时的同步函数?

由于我的问题只得到部分回答,我会自己提供解决方案,以防其他人遇到类似问题:

首先,此代码现在可以在 Chrome、Chromium 和 Firefox 的控制台中正常运行。以前没有,所以也许在这方面对 javascript 引擎进行了升级。 运行 虽然提供的 CodeSandbox 中的代码在延迟 3 秒后仍会同时记录两行。

正如人们所指出的,有两件事可能是造成这种情况的原因:

  • 编译器删除空循环
  • 只要循环 运行
  • ,控制台消息就不会刷新

此代码将解决这两个问题:

function pause(ms, start=new Date()) {
  while (new Date() - start <= ms) {
    setTimeout(()=>pause(ms,start))
  }
}

console.log("start calculation..");
pause(3000);
console.log("calculation finished!");

在允许执行事件回调之后,调用 SetTimeout(即使延迟为 0 毫秒)将导致其余代码执行(递归函数调用)返回到事件循环以供稍后处理第一的。这确保其他事件 - 例如控制台的日志记录 - 不会被阻止。

它还在循环中放置了一些实际代码,这样循环就不会被任何编译器代码优化删除。