中断并重新启动setTimeouts循环

时间:2019-10-05 00:11:51

标签: javascript

我正在尝试播放同时显示定时文本的音频文件。当按下“播放”按钮时,将选择一个随机音频文件,并加载其字幕和定时。然后使用setTimeouts循环在正确的时间用适当的文本替换现有文本。

这似乎工作正常,但问题是我需要能够中断音频并停止字幕,并且在按“播放”时可以再次工作。

这是我的代码的最低“有效”版本:

var playing = false;
var timeout;

var allSubs = [
    "A1 | A2 | A3",
    "B1 | B2 | B3 | B4",
    "C1 | C2 | C3 | C4 | C5",
]

var allTimings = [
    "0 | 2 | 4",
    "0 | 1 | 2 | 3",
    "0 | 0.5 | 1 | 1.5 | 2",
]

function playAudio() {
    playing = true;
    $('#media-control').text('Stop');

    index = Math.floor(Math.random() * Math.floor(3));

    var subtitleStr = allSubs[index];
    var timingStr = allTimings[index];

    subtitleArr = subtitleStr.split(' | ');
    timingArr = timingStr.split(' | ').map(Number);

    for (i = 0; i < subtitleArr.length; i++) {
        timeout = setTimeout((function(i) {
            return function() {
                $('#subtitle-text').text(subtitleArr[i]);
            }
        })(i), timingArr[i] * 1000);
    }
}

function stopAudio() {
    playing = false;
    clearTimeout(timeout);

    $('#media-control').text('Play');
    $('#subtitle-text').text('');
}

function toggleMedia(e) {
    if (!playing) {
        playAudio();
    } else {
        stopAudio();
    }
}

$('#media-control').bind('click', toggleMedia);

https://jsfiddle.net/eshapiro42/bjme90yt/12/

如果您快速连续按“播放” /“停止”足够多次,最终字幕将停止以正确的顺序和正确的时间出现。

有人可以建议一种更好的方式来创建定时文本,还是一种可以中断setTimeout循环的方式,这种方式实际上可以确定地起作用?

1 个答案:

答案 0 :(得分:2)

在我看来,您的问题出在playAudio函数中。您要一次遍历所有字幕,并为每个字幕设置超时。设置下一个超时ID时,您将覆盖该超时ID。因此,当您按下暂停键时,唯一真正被取消的超时是最后一个。

您需要做的是存储这些超时ID的数组。设置新的超时时,推送到阵列。当您按下暂停键时,请清除该阵列中的所有超时。

var allTimeouts = [];
...
allTimeouts.push(timeout); // On setting the timeouts
...
for(int i = 0; i < allTimeouts.length; i++){ // On clearing the timeouts 
    clearTimeout(allTimesouts[i]);
}