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

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

本文关键字:元素 打断 settimeout 显示 时间 持续时间 json      更新时间:2023-09-26

我有一个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处显示aaaaa15秒,等等。我写了一个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);

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

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

由于else条件下的每一个都会每秒显示一条"没有文本可显示"消息,即使第一个check最终决定显示第一条消息,其他两个也会迅速超过它并拒绝消息。

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

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

与其在messages数组上迭代,不如只关注第一个数组,并在完成后将其偏移。

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

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

我没有使用jQuery,只是使用了普通的JavaScript,但您应该能够很容易地对其进行调整。此外,我每500毫秒检查一次,并在消息在计划的1000毫秒内显示,以避免由于浏览器滞后或阻塞而错过任何消息。计时器和时间表并不能保证在你认为的时候准确运行,所以如果一个时间需要1001毫秒而不是1000毫秒,你就会错过一条消息!

对setTimeout的调用位置不正确。放入

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

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

printNext:中替换此代码块

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

只有

     check();

以确保在回调中删除文本。

另一种方法:

//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();
}