首頁  >  問答  >  主體

console.log() 非同步還是同步?

<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粉248602298P粉248602298419 天前490

全部回覆(2)我來回復

  • P粉930534280

    P粉9305342802023-08-28 22:01:29

    這不是問題的真正答案,但對於偶然發現這篇文章的人來說可能會很方便,而且評論太長了:

    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 都以某種方式異步,因此您可能希望在某些情況下使用這樣的函數。

    回覆
    0
  • P粉141925181

    P粉1419251812023-08-28 15:47:19

    console.log 沒有標準化,因此行為相當未定義,並且可以在開發人員工具的不同版本之間輕鬆更改。你的書可能已經過時了,我的答案也可能很快就會過時。

    對於我們的程式碼來說,console.log 是否非同步沒有任何區別,它不提供任何類型的回調等;並且您傳遞的值始終在您呼叫該函數時被引用和計算。

    我們真的不知道接下來會發生什麼(好吧,我們可以,因為 Firebug、Chrome Devtools 和 Opera Dragonfly 都是開源的)。控制台需要將記錄的值儲存在某處,並將它們顯示在螢幕上。渲染肯定會非同步發生(受到速率限制更新的限制),未來與控制台中記錄的物件的交互也會發生(例如擴展物件屬性)。

    因此控制台可能會克隆(序列化)您記錄的可變對象,或者它將儲存對它們的引用。第一個不適用於深/大物體。此外,至少控制台中的初始渲染可能會顯示物件的「目前」狀態,即記錄時的狀態 - 在您的範例中您會看到 Object {}

    但是,當您展開物件以進一步檢查其屬性時,控制台可能只儲存對物件及其屬性的引用,現在顯示它們將顯示其目前(已變異)狀態。如果按一下 ,您應該可以在範例中看到 bar 屬性。

    這是發佈在錯誤報告中的螢幕截圖解釋他們的「修復」:

    因此,某些值可能會在記錄後很久才被引用,並且對這些值的評估相當(「在需要時」)。這種差異最著名的例子是在問題Is Chrome's JavaScript console中處理的懶得評估陣列?

    解決方法是確保始終記錄物件的序列化快照,例如透過執行console.log(JSON.stringify(obj))。不過,這僅適用於非圓形和相當小的物體。另請參閱如何更改 Safari 中 console.log 的預設行為?

    更好的解決方案是使用斷點進行偵錯,其中執行完全停止,您可以檢查每個點的當前值。僅對可序列化和不可變的資料使用日誌記錄。

    回覆
    0
  • 取消回覆