console.log() 异步还是同步?
P粉248602298
P粉248602298 2023-08-27 22:31:53
0
2
552
<p>我目前正在阅读 Trevor Burnham 的《Async Javascript》。到目前为止,这是一本很棒的书。</p> <p>他谈到此代码片段和 console.log 在 Safari 和 Chrome 控制台中是“异步”的。不幸的是我无法复制这个。这是代码:</p> <pre class="brush:php;toolbar:false;">var obj = {}; console.log(obj); obj.foo = 'bar'; // my outcome: Object{}; 'bar'; // The book outcome: {foo:bar};</pre> <p>如果这是异步的,我预计结果就是书中的结果。 console.log() 被放入事件队列中,直到执行完所有代码,然后运行它并具有 bar 属性。</p> <p>看起来虽然它正在同步运行。</p> <p>我运行这段代码是错误的吗? console.log 实际上是异步的吗?</p>
P粉248602298
P粉248602298

全部回复(2)
P粉930534280

这并不是问题的真正答案,但对于偶然发现这篇文章的人来说可能会很方便,而且评论太长了:

window.console.logSync = (...args) => {
  try {
    args = args.map((arg) => JSON.parse(JSON.stringify(arg)));
    console.log(...args);
  } catch (error) {
    console.log('Error trying to console.logSync()', ...args);
  }
};

这将创建 console.log 的伪同步版本,但具有与接受的答案中提到的相同的警告。

由于目前看来大多数浏览器的 console.log 都以某种方式异步,因此您可能希望在某些情况下使用这样的函数。

P粉141925181

console.log 没有标准化,因此行为相当未定义,并且可以在开发人员工具的不同版本之间轻松更改。你的书可能已经过时了,我的答案也可能很快就会过时。

对于我们的代码来说,console.log 是否异步没有任何区别,它不提供任何类型的回调等;并且您传递的值始终在您调用该函数时被引用和计算。

我们真的不知道接下来会发生什么(好吧,我们可以,因为 Firebug、Chrome Devtools 和 Opera Dragonfly 都是开源的)。控制台需要将记录的值存储在某处,并将它们显示在屏幕上。渲染肯定会异步发生(受到速率限制更新的限制),未来与控制台中记录的对象的交互也会发生(例如扩展对象属性)。

因此控制台可能会克隆(序列化)您记录的可变对象,或者它将存储对它们的引用。第一个不适用于深/大物体。此外,至少控制台中的初始渲染可能会显示对象的“当前”状态,即记录时的状态 - 在您的示例中您会看到 Object {}

但是,当您展开对象以进一步检查其属性时,控制台可能只存储对对象及其属性的引用,现在显示它们将显示其当前(已变异)状态。如果单击 +,您应该能够在示例中看到 bar 属性。

这是发布在错误报告中的屏幕截图解释他们的“修复”:

因此,某些值可能会在记录后很久才被引用,并且对这些值的评估相当(“在需要时”)。这种差异最著名的例子是在问题Is Chrome's JavaScript console中处理的懒得评估数组?

解决方法是确保始终记录对象的序列化快照,例如通过执行console.log(JSON.stringify(obj))。不过,这仅适用于非圆形和相当小的物体。另请参阅如何更改 Safari 中 console.log 的默认行为?

更好的解决方案是使用断点进行调试,其中执行完全停止,您可以检查每个点的当前值。仅对可序列化和不可变的数据使用日志记录。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板