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

Javascript 我想根据json中的元素的时间和持续时间显示它们,并且间隔被settimeout打断,javascript,jquery,json,logic,Javascript,Jquery,Json,Logic,我有一个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

我有一个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.
我的网页上有一个div
user text
,我想用这个json中的字符串填充它。但是有一个条件-我想在指定给它的时间和指定给它的持续时间内显示第一个文本。 因此,根据我的示例,我想在
2015-10-07 23:25:29等处显示
aaaaaa
,显示
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++;
    }
但不知怎么的,它不起作用。发生的情况是,每秒运行的内部循环受到整个函数设置的超时的干扰。 因此,即使我们在这里找到匹配项
如果(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
实例展示

由于else条件下的每一个都将每秒显示“没有要显示的文本”消息,因此即使第一个
检查
最终决定显示第一条消息,其他两个也将很快超越它并说没有消息

您可以将
setTimeout
调用
printNext
移动到
if
的真正分支中的
check
函数中

我用另一种方法构建了一个小演示:

它不会迭代
消息
数组,而是只关注第一个,完成后将其关闭

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

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

我没有使用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();
}
//用于为每个新消息生成元素id的全局变量
var消息_索引=0;
函数get_schedule(){
$.getJSON('get_json.php',函数(json){
附表信息(json);
});
}
功能计划\信息(计划){
var current_time=新日期();
//遍历每个消息事件
对于(变量i=0;i当前时间){
var duration=计划[i]。文本_duration*1000;
//计算邮件放置和删除之前的时间
var显示延迟=开始时间-当前时间;
var remove\u delay=开始时间-当前时间+持续时间;
//安排消息的放置
(功能(延迟、消息、索引){
setTimeout(函数(){
显示_消息(消息、索引);
},延误);
})(显示延迟,计划[i]。文本内容,消息索引);
//计划删除邮件
(功能(延迟、索引){
setTimeout(函数(){
删除_消息(索引);
},延误);
})(删除延迟、消息索引);
//用于下一条消息的增量全局消息索引
消息索引++;
}
}
}
//在这里你喜欢jQuery效果吗。。。
功能显示信息(信息、索引){
$('#用户文本')。追加(
$(“”)
.html(信息)
.attr(“id”,“消息-”+索引)
);
}
//…这里呢
函数删除消息(索引){
$(“#消息-”+索引).remove();
}

还有一件事-是否有办法在旁边引入另一个div,例如#time并在那里打印每秒更新的当前时间?我在这里为它创建了另一个问题