如果JavaScript(大部分)是同步的和单线程的,为什么while循环没有阻止进一步语句的执行

If JavaScript is (mostly) synchronous and single threaded, why does a while loop not block execution of further statements?

本文关键字:循环 while 执行 语句 进一步 为什么 大部分 JavaScript 单线程 同步 如果      更新时间:2023-09-26

我是JavaScript新手!我试图在JavaScript程序中做一个非常天真的阻塞语句。我认为JavaScript是单线程的(除了像setTimeout这样的东西),并且在代码块中是同步的,所以我希望我可以用while循环来阻止代码的执行。我不想使用setTimeout,因为我不确定它是否足够精确,可以做我想做的事情。

让我解释一下。我有一个按钮与class="playback",它应该触发一系列的声音播放。回调发出AJAX请求,然后将数据传递给playbackRecording()。这个函数接受一个有两个属性的对象列表:key_pressed(帮助确定播放哪个声音,但对这个问题不重要)和time_to_next_key(等待下一个声音播放的毫秒数)。actionApp()是使声音实际播放的函数。

我的期望:第一个声音播放。过了一小段时间,下一个动作就发生了。重复,直到完成。

实际情况:经过的时间等于所有按键的time_to_next_key的总和,然后在结束时播放所有声音。

function playbackRecording(content) {
    var waitTime = 0;
    var keypress = content[0];
    actionApp(keypress.key_pressed);
    for (var i = 1; i < content.length; i++) {
        waitTime += keypress.time_to_next_key;
        keypress = content[i];
        var end = Date.now() + waitTime;
        while(Date.now() < end) {}
        actionApp(keypress.key_pressed);
    }
}
function playbackLinkClicked(evt) {
    var urlString = '/fetch_recording/' + this.id;
    $.get(urlString, function(data){
        if (data.status === 'success') {
            playbackRecording(data.content);
        } else {
            alert('Could not load recording.');
        }
    });
}
$('.playback').click(playbackLinkClicked);

我错过了什么?

播放声音是由异步代码完成的(我不知道actionApp()到底做了什么,但你描述的行为与此一致,这是大多数交互式代码在Javascript中的工作方式)。当你调用actionApp()时,它把这段代码放到事件队列上。在Javascript返回到主事件循环之前,它实际上不会播放任何内容。

while循环是同步的,所以你的代码在它们全部完成之前不会返回。每次调用actionApp()时,它都会向事件队列中添加另一个声音。然后,当它完成时,所有排队的动作被执行。