JS i/o sequence

JS i/o sequence

本文关键字:sequence JS      更新时间:2023-09-26

我有三个函数被这样调用:

<body onLoad="startIt(),mssTmt(),timeout()">

它们是:

function startIt(){
    document.write('Timeout has started!');
}
function timeout(){
    function sleep(milliSeconds) {
        var startTime = new Date().getTime();
        var cnt=0;
        while (new Date().getTime() < startTime + milliSeconds){
            cnt++;
            if(cnt%1000000==0)
                console.log('time expired: '+(new Date().getTime())+'<br>');
        }
    }
    sleep(3000);
}
function mssTmt(){
    var greeting = 'Hello, I am awake!';
    document.write('<hr>'+greeting);
}

所以我期待以下内容:

  1. 它将写为"超时已开始!"页面加载后立即显示在页面上
  2. 接下来会写上"你好,我醒了!"
  3. 然后,在函数超时的循环中生成的日志将依次输出到控制台中。但没有那种。事实上,首先出现的是函数timeout()中的循环。因此,我看到了所有这些日志消息,只有在之后,我才能在页面上编写的函数startIt()和mssTmt()中获得消息。我必须承认这对我来说是不寻常的。为什么会有这样的序列?我有一些假设,但当然,从真正的JS大师那里得到确切的解释会更好!Plsss

在RoryKoehein回答后更新我读了他通过链接给我的东西,但有些东西仍然无法理解。

我稍微更改了一下代码。现在是来电者:

function getStarted(){
    console.log(new Date().getTime()+' > getStarted() has been called');
  try{
    startIt();
    mssTmt();
timeout();
  }catch(e){
    alert(e.message);
  }
}

<a href="javascript:void();" onclick="getStarted();" id="getstarted">Get started!</a>

取而代之的是

<body onLoad="startIt(),mssTmt(),timeout()"> 

首先,会发生这样的事情:如果我在调用每个函数之前添加一个alert(),那么序列与代码中的序列完全相同——startIt()、mssTmt()、timeout()。所有实现都被阻止,直到我点击警报弹出窗口。请看插图。如果我删除警报,它的工作原理与前面一样(请参阅问题的起点)。那么,如果警报阻止了所有流程,为什么它会更改执行顺序(i/o)?接下来,当我试图通过setTimeout()调用函数timeout()时,我注意到了一个奇怪的脚本行为;此处:http://javascript.info/tutorial/events-and-timing-depth#the-settimeout-func-0-trick是这样写的setTimeout(..,0)技巧用于在堆叠事件之后执行代码,并修复与定时相关的问题。如果我这样修改代码:setTimeout(timeout,[delay]);它一直在不可预测地进行:

  • 如果我将延迟设置为0,则它只在函数timeout()已完成
  • 如果我增加延迟,有时它会输出(startIt(),mssTmt())BEFORE循环,有时在之后,取决于延迟值

但最奇怪的是,在所有这些尝试中,即使具有相同的延迟值,I/O的顺序也变得不同!例如:setTimeout(超时,3);有时它会导致函数startIt()、mssTmt()中的首次输出,有时反之亦然–timeout()。老实说,我不知道这是什么意思…

这很好地解释了这一点:http://javascript.info/tutorial/events-and-timing-depth#javascript-执行和呈现

最重要的是:

在大多数浏览器中,渲染和JavaScript使用单个事件队列。这意味着当JavaScript运行时,不会发生任何渲染。

while循环完全阻塞线程三秒钟。document.write调用被添加到事件队列中,甚至可能被执行,但绘制事件发生在JS不再阻塞之后。

如果你打开Chrome的开发者工具时间轴,你可以确切地看到浏览器在做什么(https://developers.google.com/chrome-developer-tools/docs/timeline)。

离题:我想这是测试代码。在任何情况下都不应该在生产中使用这样的东西。在body标记[1]中内联堆叠多个函数,使用document.write[2]和阻塞while循环都是不好的做法[3]。

1个窗口打开与<车身负载=">2为什么document.write被认为是";不良做法"?3 sleep()的JavaScript版本是什么?