为什么SetInterval在传递php字符串后停止执行

时间:2017-08-19 12:36:52

标签: javascript php

我有这段代码:

    <p id="demo"></p>

<script>
// Set the date we're counting down to
var countDownDate = new Date("<?php echo $starttime; ?>").getTime();

// Update the count down every 1 second
var x = setInterval(function() {

  // Get todays date and time
  var now = new Date("<?php echo $nowtime; ?>").getTime();

  // Find the distance between now an the count down date
  var distance = - countDownDate + now;
  // Time calculations for days, hours, minutes and seconds
  var days = Math.floor(distance / (1000 * 60 * 60 * 24));
  var hoursdiff = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
  var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
  var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
  var seconds = Math.floor((distance % (1000 * 60)) / 1000);

  // Display the result in the element with id="demo"
  document.getElementById("demo").innerHTML = days + "d " + hours + "h "
  + minutes + "m " + seconds + "s ";

  // If the count down is finished, write some text 
  if (distance < 0) {
    clearInterval(x);
    document.getElementById("demo").innerHTML = "EXPIRED";
  }
}, 1000);
</script> 

它执行并计算从DB中提取的2个日期之间的时差。它应该每秒更新差异作为秒表,但由于某种原因,它显示差异一次,间隔功能停止工作。

但如果我从&#39;现在&#39;删除"<?php echo $nowtime; ?>"变量,它开始像魅力一样工作。

2 个答案:

答案 0 :(得分:0)

为什么不简单地使用javascript方法Date().getTime(),而不是尝试在实际函数中使用php来获取当前时间(现在)?页面加载后,php变量不会更新,因此日期函数将始终引用相同的时间

<p id="demo"></p>

<script>
    <?php
        /* example date */
        $starttime='2017-08-20 14:30:30';

        echo "
            var countDownDate = new Date('$starttime').getTime();
        ";
    ?>

    (function(time){
        var now=new Date().getTime();

        // Find the distance between now an the count down date
        var distance = countDownDate - now;

        // Time calculations for days, hours, minutes and seconds
        var days = Math.floor(distance / (1000 * 60 * 60 * 24));
        var hoursdiff = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
        var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
        var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
        var seconds = Math.floor((distance % (1000 * 60)) / 1000);

        t=setTimeout( arguments.callee, time );

        if( distance <= 0 ){
            clearTimeout( t );
            return false;
        }
        document.getElementById("demo").innerHTML = days + "d " + hours + "h " + minutes + "m " + seconds + "s ";
    })(1000);
</script>

为了在不使用ajax长轮询的情况下实现服务器时间的持续轮询,我认为Server Sent Events是理想的。下面的第一个脚本是SSE中使用的服务器组件 - 它每隔X秒将格式化的消息发送回javascript客户端,在这种情况下每1秒发送一次。

<?php

    /* sse-time.php */
    set_time_limit( 0 );
    ini_set('auto_detect_line_endings', 1);
    ini_set('max_execution_time', '0');
    ob_end_clean();

    $sleep = 1; /* send message back every X seconds */
    $startdate = !empty( $_GET['start'] ) ? $_GET['start'] : false;
    $evt = !empty( $_GET['evt'] ) ? $_GET['evt'] : 'time';

    if( $startdate ){
        /* 
        utility function to send formatted response
        */
        function sse( $evtname='sse', $data=null, $retry=1000 ){
            if( !is_null( $data ) ){
                echo "event:".$evtname."\r\n";
                echo "retry:".$retry."\r\n";
                echo "data:" . json_encode( $data, JSON_FORCE_OBJECT | JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS );
                echo "\r\n\r\n";
            }
        }
        /*
            Important to set correct headers
        */
        header('Content-Type: text/event-stream'); 
        header('Cache-Control: no-cache');
        header('Access-Control-Allow-Credentials: true');
        header('Access-Control-Allow-Methods: GET');
        header('Access-Control-Expose-Headers: X-Events');

        /* Infinite loop */
        while( true ){
            if( connection_status() != CONNECTION_NORMAL or connection_aborted() ) {
                break;
            }

            /* If the current date/time is greater than countdown target, exit loop */
            if( time() > $startdate ) break;

            /* construct the payload */
            $payload=array(
                'event'     =>  $evt,
                'date'      =>  date( 'Y-m-d H:i:s' ),
                'start'     =>  $startdate
            );
            /* send the payload */
            call_user_func( 'sse', $evt, $payload );

            /* -- Send output -- */
            if( @ob_get_level() > 0 ) for( $i=0; $i < @ob_get_level(); $i++ ) @ob_flush();
            @flush();

            /* wait for defined period before repeating loop */
            sleep( $sleep );
        } //end infinite loop

        if( @ob_get_level() > 0 ) {
            for( $i=0; $i < @ob_get_level(); $i++ ) @ob_flush();
            @ob_end_clean();
        }
    }
?>

客户端组件包含在一个基本的html页面中,以显示wholoe的工作原理。

<?php
    /* countdown */
    $starttime='2017-08-21 10:58:30';
?>

<!doctype html>
<html>
    <head>
        <title>SSE Countdown</title>
        <script>
            <?php
                echo " var countDownDate = new Date('$starttime').getTime();";
            ?>
            function bindEvtSource(){
                var evtname='time';
                var url='https://sentinel/assets/sse-time.php?start='+countDownDate+'&evt='+evtname;
                var demo=document.getElementById('demo');

                if ( !!window.EventSource ) {
                    var evtSource = new EventSource( url );

                    evtSource.addEventListener( 'error', function(e){
                        console.error('%o %s',e,e.type);
                    },false);

                    evtSource.addEventListener( evtname, function(e){
                        var json=JSON.parse(e.data);


                        var now=new Date( json.date ).getTime();
                        var distance = countDownDate - now;
                        var days = Math.floor(distance / (1000 * 60 * 60 * 24));
                        var hoursdiff = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
                        var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
                        var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
                        var seconds = Math.floor((distance % (1000 * 60)) / 1000);

                        demo.innerHTML = days + "d " + hours + "h " + minutes + "m " + seconds + "s ";
                        if( distance <= 0 ){
                            evtSource.close();
                            demo.innerHTML='EXPIRED';
                        }
                    },false);
                } else {
                    demo.innerHTML='Server Sent Events are not supported in this browser';
                }
            }
            document.addEventListener( 'DOMContentLoaded', bindEvtSource, false );
        </script>
    </head>
    <body>
        <p id='demo'></p>
    </body>
</html>

答案 1 :(得分:0)

很抱歉迟到的回复。

我决定用javascript来更新我从db中获取的时差。具体来说,我正在刷新页面的一部分而不是整个页面。它现在就像一个秒表。

1)启动计数器

<a href="http://127.0.0.1:4567/home_controller/startcount">start count</a><br>
                <?php if (!empty($timer->start)){$date1=date_create($timer->start);
                $date2=date_create(date('Y-m-d H:i:s'));
                $diff=date_diff($date1,$date2);
                $days = $diff->format("%d");
                $hours = $diff->format("%h");
                $minutes = $diff->format("%i")/60;
                $seconds = $diff->format("%s")/360;
                $timediff = $hours+$minutes+$seconds;}
 ?>

2)刷新显示时差的部分。

<div id="scope"><?php if (!empty($timer->start)){echo $diff->format("%d days %h hours %i minutes %s seconds");} ?></div> <script type="text/javascript">
     var $scores = $("#scores");
setInterval(function () {$("#scope").load("http://127.0.0.1:4567/home_controller/ #scope");
}, 1000);
 </script>