我想根据时间和持续时间显示 json 中的元素,并且间隔被 settimeout 中断

I want to display elements from json based on their time and duration and interval is interupted by settimeout

我有一个 json 文件,其结构如下:

[{"text_content":"aaaaa","text_duration":15,"start_time":"2015-10-07 23:25:29"},
{"text_content":"aawwaaaaa","text_duration":15,"start_time":"2015-10-07 23:25:44"},
{"text_content":"bbaawwaaaaa","text_duration":15,"start_time":"2015-10-07 23:25:59"}, etc.

我的网页 user-text 上有一个 div,我想用取自 json 的字符串填充它。但是有一个条件——我想在分配给它的时间和分配给它的持续时间内显示第一个文本。 因此,根据我的示例,我想在 2015-10-07 23:25:29 处显示 aaaaa 15 秒,等等。 我写了一个 jquery 脚本:

    var results =[];
    var cursor = 0;

    function myFunction () {
        $.getJSON('get_json.php', function(json) {
            results = json;
            cursor = 0;

            // Now start printing
            if(results.length == 0){
                $('#user-text').hide('fast', function() {
                    $('#user-text').html("there is no text at the moment");
                    $('#user-text').show('fast');
                });
            }else{
                printNext();
            }
        });
    }

    function printNext(){
        if(cursor == results.length){
            // Reset the cursor back to the beginning.
            cursor = 0;
        }

        var textDate = results[cursor].start_time;
        var textMsg = results[cursor].text_content;
        var dateOfText = new Date(textDate).setMilliseconds(0);
        var duration = results[cursor].text_duration;
        //now we're checking every second if there is any text to display at that time
        var myInterval = setInterval(check, 1000);

        function check() {

            var currentDate = new Date().setMilliseconds(0);

            if (currentDate - dateOfText ==0) {
            clearInterval(myInterval);
                $('#user-text').hide('fast', function() {
                    $('#user-text').html(textMsg);
                    $('#user-text').show('fast');
                });

            } else{

                $('#user-text').html("there is no text to display at the moment");
            }
        }

        // Set a delay for the current item to stay
        // Delay is key2 * 1000 seconds
        setTimeout(function(){
            printNext();
        }, results[cursor].text_duration * 1000);

        // Advance the cursor.
        cursor++;
    }

但不知何故它不起作用。发生的情况是每秒进行一次的内部循环受到整个函数的设置超时的干扰。 因此,即使我们在这里找到匹配项 if (currentDate - dateOfText ==0) { - 它也不会在整个持续时间内出现在屏幕上,因为它会被以下内容打断:

setTimeout(function(){
            printNext();
        }, results[cursor].text_duration * 1000);

我不知道在这一点上如何继续以及如何使逻辑工作以便每个文本都在其整个持续时间内播放。你能帮我吗?

setTimeout 的调用位置不当。放

    setTimeout(printNext, results[cursor].text_duration * 1000);

在与clearInterval(myInterval);相同的{}代码块中,即停止间隔定时器,显示文本,并启动一个定时器回调printNext擦除文本和检查新的。

替换printNext中的这段代码:

    setTimeout(function(){
        printNext();
    }, results[cursor].text_duration * 1000);

只有

     check();

确保在回调中删除文本。

因为你在 check 里面有 else 条件来隐藏文本。我假设这些要显示的消息会提前到达,所以在消息准备好时,您将同时拥有三个 check 运行ning 实例被显示。

因为 else 条件下的每个人都会每秒显示 "there is no text to display" 消息,即使第一个 check 最终决定显示第一条消息,其他两个也会快速结束运行 并拒绝留言。

您可以将调用 printNextsetTimeout 移动到 if 的真实分支中的 check 函数内部。

我用另一种方法构建了一个小演示:http://jsfiddle.net/nauzilus/rqctam5r/

它不会遍历 messages 数组,它只会关注第一个数组,并在完成后将其关闭。

您可以将新条目推送到 messages,它们将在适当的时候排队显示。

此外,这假设消息总是会提前加载;任何具有过去日期的消息都将被处理,就好像它们现在就可以被查看一样。

我没用过 jQuery,只是普通的 JavaScript,但您应该能够很容易地适应它。 此外,我每 500 毫秒检查一次,并在消息在计划的 1000 毫秒以内时显示,以避免由于浏览器延迟或阻塞而错过任何消息。计时器和日程安排不能保证 运行 完全按照您的预期进行,因此如果时间花费 1001 毫秒而不是 1000 毫秒,您将错过一条消息!

另一种方法:

//global variable used to generate the element id for each new message
var message_index = 0;

function get_schedule() {
    $.getJSON('get_json.php', function(json) {
        schedule_messages(json);
    });
}

function schedule_messages(schedule) {
    var current_time = new Date();

    //iterate through each message event
    for(var i = 0; i < schedule.length; i++) {
        var start_time = new Date(schedule[i].start_time);

        //make sure the scheduled message time has not passed
        if(start_time > current_time) {

            var duration = schedule[i].text_duration * 1000;

            //calculate time until message placement and removal
            var display_delay = start_time - current_time;
            var remove_delay = start_time - current_time + duration;

            //schedule placement of the message
            (function(delay, message, index) {
                setTimeout(function() {
                    display_message(message, index);
                }, delay);
            })(display_delay, schedule[i].text_content, message_index);

            //schedule removal of the message
            (function(delay, index) {
                setTimeout(function() {
                    remove_message(index);
                }, delay);
            })(remove_delay, message_index);

            //increment global message index to use for next message
            message_index++;
        }
    }
}

//do your fancy jQuery effect(s) in here...
function display_message(message, index) {
    $('#user-text').append(
        $("<p>")
            .html(message)
            .attr("id", "message-" + index)
    );
}

//... and here
function remove_message(index) {
    $("#message-" + index).remove();
}